home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / xwindows / demos / xfract_1.z / xfract_1 / xfractint-1.06 / editpal.c < prev    next >
C/C++ Source or Header  |  1992-09-28  |  68KB  |  3,012 lines

  1. /*
  2.  * editpal.c
  3.  *
  4.  * Edits VGA 256-color palettes.
  5.  *
  6.  * This module is linked as an overlay, use ENTER_OVLY and EXIT_OVLY.
  7.  *
  8.  *
  9.  * Key to initials:
  10.  *
  11.  *    EAN - Ethan Nagel [70022,2552]
  12.  *
  13.  *    JJB - Juan J. Buhler [jbuhler@gidef.edu.ar]
  14.  *
  15.  * Revision History:
  16.  *
  17.  *   10-22-90 EAN     Initial release.
  18.  *
  19.  *   10-23-90 EAN     "Discovered" get_line/put_line functions, integrated
  20.  *                them in (instead of only getcolor/putcolor). Much
  21.  *                faster!
  22.  *              Redesigned color editors (now at top of palette) and
  23.  *                re-assigned some keys.
  24.  *              Added (A)uto option.
  25.  *              Fixed memory allocation problem.  Now uses shared
  26.  *                FRACTINT data area (strlocn).  Uses 6 bytes DS.
  27.  *
  28.  *   10-27-90 EAN     Added save to memory option - will save screen image to
  29.  *                memory, if enough mem avail.  (disk otherwise).
  30.  *              Added s(T)ripe mode - works like (S)hade except only
  31.  *                changes every n'th entry.
  32.  *              Added temporary palette save/restore.  (Can work like
  33.  *                an undo feature.)  Thanks to Pieter Branderhorst for
  34.  *                idea.
  35.  *
  36.  *   10-28-90 EAN     The (H)ide function now makes the palette invisible,
  37.  *                while allowing any other operations (except '\\' -
  38.  *                move/resize) to continue.
  39.  *
  40.  *   10-29-90 PB (in EAN's absence, <grin>)
  41.  *              Change 'c' to 'd' and 's' to '=' for below.
  42.  *              Add 'l' to load palette from .map, 's' to store .map.
  43.  *              Add 'c' to invoke color cycling.
  44.  *              Change cursor to use whatever colors it can from
  45.  *              the palette (not fixed 0 and 255).
  46.  *              Restore colors 0 and 255 to real values whenever
  47.  *              palette is not on display.
  48.  *              Rotate 255 colors instead of 254.
  49.  *              Reduce cursor blink rate.
  50.  *
  51.  *   11-15-90 EAN     Minor "bug" fixes.  Continuous rotation now at a fixed
  52.  *                rate - once every timer tick (18.2 sec);  Blanks out
  53.  *                color samples when rotating; Editors no longer rotate
  54.  *                with the colors in color rotation mode;  Eliminated
  55.  *                (Z)oom mode; other minor fixes.
  56.  *
  57.  *   01-05-91 PB      Add 'w' function to convert to greyscale.
  58.  *
  59.  *   01-16-91 PB      Change rotate function to use new cyclerange stuff.
  60.  *
  61.  *   01-29-91 EAN     Made all colors editable.  The two reserved colors are
  62.  *             X'ed out.  They can be edited but the color is not
  63.  *             visible.  (There is an X over the sample instead.)
  64.  *              Changed default reserved colors to 254 & 255.
  65.  *              Added 'v' command to set the reserved colors to those
  66.  *             under the editors.
  67.  *              Added 'o' command to set the rotate range to between
  68.  *                the two editors.
  69.  *              Modified 'w' function:
  70.  *                uses internal function to do conversion (not BIOS)
  71.  *                will convert only current color if in 'x' mode or
  72.  *              range between editors in 'y' mode or entire palette
  73.  *              if in "normal" mode.
  74.  *
  75.  *   02-08-91 EAN     Improved 16 color support.  In 16 color mode, colors
  76.  *                16-255 have a dot over them and are editable but not
  77.  *                visible (like the two reserved colors).
  78.  *
  79.  *   09-08-91 SWT     Added 'n' command to make a negative color palette:
  80.  *                      will convert only current color if in 'x' mode or
  81.  *                      range between editors in 'y' mode or entire palette
  82.  *                      if in "normal" mode.
  83.  *
  84.  *   03-03-92 JJB     Added '!', '@' and '#' commands to swap RG, GB and
  85.  *                      RB columns (sorry, I didn't find better keys)
  86.  *
  87.  *
  88.  */
  89.  
  90.  
  91.  
  92. #include <stdio.h>
  93. #include <stdlib.h>
  94. #include <string.h>
  95. #ifndef XFRACT
  96. #include <stdarg.h>
  97. #include <dos.h>     /* for FP_SEG & FP_OFF */
  98. #else
  99. #include <varargs.h>
  100. #endif
  101. #include <math.h>
  102.  
  103. #ifdef __TURBOC__
  104. #   include <mem.h>   /* to get mem...() declarations */
  105. #endif
  106.  
  107. #include "fractint.h" /* for overlay stuff */
  108. #include "prototyp.h"
  109.  
  110.  
  111. /*
  112.  * misc. #defines
  113.  */
  114.  
  115. #define FONT_DEPTH        8      /* font size */
  116.  
  117. #define CSIZE_MIN        8      /* csize cannot be smaller than this */
  118.  
  119. #define CURSOR_SIZE        5      /* length of one side of the x-hair cursor */
  120.  
  121. #define CURSOR_BLINK_RATE   3      /* timer ticks between cursor blinks */
  122.  
  123. #define FAR_RESERVE     8192L      /* amount of far mem we will leave avail. */
  124.  
  125. #define MAX_WIDTH     1024      /* palette editor cannot be wider than this */
  126.  
  127. #define FILENAME "FRACTINT.$$1"   /* file where screen portion is */
  128.                   /* stored */
  129.  
  130. #define TITLE   "FRACTINT"
  131.  
  132. #define TITLE_LEN (8)
  133.  
  134.  
  135. #define newx(size)     mem_alloc(size)
  136. #define new(class)     (class *)(mem_alloc(sizeof(class)))
  137. #define delete(block)
  138.  
  139. #ifdef XFRACT
  140. int editpal_cursor = 0;
  141. #endif
  142.  
  143.  
  144. /*
  145.  * Stuff from fractint
  146.  */
  147.  
  148. extern BYTE dacbox[256][3];     /* DAC spindac() will use         */
  149. extern int         sxdots;         /* width of physical screen         */
  150. extern int         sydots;         /* depth of physical screen         */
  151. extern int         sxoffs;         /* start of logical screen         */
  152. extern int         syoffs;         /* start of logical screen         */
  153. extern int         lookatmouse;     /* mouse mode for getakey(), etc    */
  154. extern int         strlocn[];      /* 10K buffer to store classes in   */
  155. extern int         colors;         /* # colors avail.             */
  156. extern int         color_dark;     /* darkest color in palette         */
  157. extern int         color_medium;     /* nearest to medbright gray color  */
  158. extern int         rotate_lo, rotate_hi;
  159.  
  160.  
  161.  
  162. /*
  163.  * basic data types
  164.  */
  165.  
  166.  
  167. typedef struct
  168.    {
  169.    BYTE red,
  170.          green,
  171.          blue;
  172.    } PALENTRY;
  173.  
  174.  
  175. typedef BYTE BOOLEAN;
  176.  
  177.  
  178.  
  179. /*
  180.  * static data
  181.  */
  182.  
  183.  
  184. static BYTE far *font8x8;
  185. static BYTE     *line_buff;   /* must be alloced!!! */
  186. static BYTE      fg_color,
  187.               bg_color;
  188. static BOOLEAN          reserve_colors;
  189. static BOOLEAN          inverse;
  190.  
  191. static float    gamma_val = 1.0;
  192.  
  193.  
  194. /*
  195.  * Interface to FRACTINT's graphics stuff
  196.  */
  197.  
  198.  
  199. static void setpal(int pal, int r, int g, int b)
  200.    {
  201.    dacbox[pal][0] = r;
  202.    dacbox[pal][1] = g;
  203.    dacbox[pal][2] = b;
  204.    spindac(0,1);
  205.    }
  206.  
  207.  
  208. static void setpalrange(int first, int how_many, PALENTRY *pal)
  209.    {
  210.    memmove(dacbox+first, pal, how_many*3);
  211.    spindac(0,1);
  212.    }
  213.  
  214.  
  215. static void getpalrange(int first, int how_many, PALENTRY *pal)
  216.    {
  217.    memmove(pal, dacbox+first, how_many*3);
  218.    }
  219.  
  220.  
  221. static void clip_put_line(int row, int start, int stop, BYTE *pixels)
  222.    {
  223.    if ( row < 0 || row >= sydots || start > sxdots || stop < 0 )
  224.       return ;
  225.  
  226.    if ( start < 0 )
  227.       {
  228.       pixels += -start;
  229.       start = 0;
  230.       }
  231.  
  232.    if ( stop >= sxdots )
  233.       stop = sxdots - 1;
  234.  
  235.    if ( start > stop )
  236.       return ;
  237.  
  238.    put_line(row, start, stop, pixels);
  239.    }
  240.  
  241.  
  242. static void clip_get_line(int row, int start, int stop, BYTE *pixels)
  243.    {
  244.    if ( row < 0 || row >= sydots || start > sxdots || stop < 0 )
  245.       return ;
  246.  
  247.    if ( start < 0 )
  248.       {
  249.       pixels += -start;
  250.       start = 0;
  251.       }
  252.  
  253.    if ( stop >= sxdots )
  254.       stop = sxdots - 1;
  255.  
  256.    if ( start > stop )
  257.       return ;
  258.  
  259.    get_line(row, start, stop, pixels);
  260.    }
  261.  
  262.  
  263. static void clip_putcolor(int x, int y, int color)
  264.    {
  265.    if ( x < 0 || y < 0 || x >= sxdots || y >= sydots )
  266.       return ;
  267.  
  268.    putcolor(x, y, color);
  269.    }
  270.  
  271.  
  272. static int clip_getcolor(int x, int y)
  273.    {
  274.    if ( x < 0 || y < 0 || x >= sxdots || y >= sydots )
  275.       return (0);
  276.  
  277.    return ( getcolor(x, y) );
  278.    }
  279.  
  280.  
  281. static void hline(int x, int y, int width, int color)
  282.    {
  283.    memset(line_buff, color, width);
  284.    clip_put_line(y, x, x+width-1, line_buff);
  285.    }
  286.  
  287.  
  288. static void vline(int x, int y, int depth, int color)
  289.    {
  290.    while (depth-- > 0)
  291.       clip_putcolor(x, y++, color);
  292.    }
  293.  
  294.  
  295. static void getrow(int x, int y, int width, char *buff)
  296.    {
  297.    clip_get_line(y, x, x+width-1, (BYTE *)buff);
  298.    }
  299.  
  300.  
  301. static void putrow(int x, int y, int width, char *buff)
  302.    {
  303.    clip_put_line(y, x, x+width-1, (BYTE *)buff);
  304.    }
  305.  
  306.  
  307. static void vgetrow(int x, int y, int depth, char *buff)
  308.    {
  309.    while (depth-- > 0)
  310.       *buff++ = clip_getcolor(x, y++);
  311.    }
  312.  
  313.  
  314. static void vputrow(int x, int y, int depth, char *buff)
  315.    {
  316.    while (depth-- > 0)
  317.       clip_putcolor(x, y++, (BYTE)(*buff++));
  318.    }
  319.  
  320.  
  321. static void fillrect(int x, int y, int width, int depth, int color)
  322.    {
  323.    while (depth-- > 0)
  324.       hline(x, y++, width, color);
  325.    }
  326.  
  327.  
  328. static void rect(int x, int y, int width, int depth, int color)
  329.    {
  330.    hline(x, y, width, color);
  331.    hline(x, y+depth-1, width, color);
  332.  
  333.    vline(x, y, depth, color);
  334.    vline(x+width-1, y, depth, color);
  335.    }
  336.  
  337.  
  338. static void displayc(int x, int y, int fg, int bg, int ch)
  339.    {
  340.    int              xc, yc;
  341.    BYTE      t;
  342.    BYTE far *ptr;
  343.  
  344.    ptr = ((BYTE far *)font8x8) + ch*FONT_DEPTH;
  345.  
  346.    for (yc=0; yc<FONT_DEPTH; yc++, y++, ++ptr)
  347.       {
  348.       for (xc=0, t= *ptr; xc<8; xc++, t<<=1)
  349.      line_buff[xc] = (t&0x80) ? (unsigned)fg : (unsigned)bg;
  350.       putrow(x, y, 8, (char *)line_buff);
  351.       }
  352.    }
  353.  
  354.  
  355. #ifndef XFRACT
  356. static void displayf(int x, int y, int fg, int bg, char *format, ...)
  357. #else
  358. static void displayf(va_alist)
  359. va_dcl
  360. #endif
  361.    {
  362.    char buff[81];
  363.    int  ctr;
  364.  
  365.    va_list arg_list;
  366.  
  367. #ifndef XFRACT
  368.    va_start(arg_list, format);
  369. #else
  370.    int x,y,fg,bg;
  371.    char *format;
  372.  
  373.    va_start(arg_list);
  374.    x = va_arg(arg_list,int);
  375.    y = va_arg(arg_list,int);
  376.    fg = va_arg(arg_list,int);
  377.    bg = va_arg(arg_list,int);
  378.    format = va_arg(arg_list,char *);
  379. #endif
  380.    vsprintf(buff, format, arg_list);
  381.    va_end(arg_list);
  382.  
  383.    for(ctr=0; buff[ctr]!='\0'; ctr++, x+=8)
  384.       displayc(x, y, fg, bg, buff[ctr]);
  385.    }
  386.  
  387.  
  388. /*
  389.  * create smooth shades between two colors
  390.  */
  391.  
  392.  
  393. static void mkpalrange(PALENTRY *p1, PALENTRY *p2, PALENTRY pal[], int num, int skip)
  394.    {
  395.    int      curr;
  396.    double rm = (double)((int) p2->red   - (int) p1->red  ) / num,
  397.       gm = (double)((int) p2->green - (int) p1->green) / num,
  398.       bm = (double)((int) p2->blue  - (int) p1->blue ) / num;
  399.  
  400.    for (curr=0; curr<num; curr+=skip)
  401.       {
  402.       if (gamma_val == 1)
  403.           {
  404.       pal[curr].red   = (p1->red   == p2->red  ) ? p1->red   :
  405.           (int) p1->red   + (int) ( rm * curr );
  406.       pal[curr].green = (p1->green == p2->green) ? p1->green :
  407.           (int) p1->green + (int) ( gm * curr );
  408.       pal[curr].blue  = (p1->blue  == p2->blue ) ? p1->blue  :
  409.           (int) p1->blue  + (int) ( bm * curr );
  410.       }
  411.       else
  412.       {
  413.       pal[curr].red   = (p1->red   == p2->red  ) ? p1->red   :
  414.           (int) p1->red   + pow(curr/(double)(num-1),gamma_val)*num*rm;
  415.       pal[curr].green = (p1->green == p2->green) ? p1->green :
  416.           (int) p1->green + pow(curr/(double)(num-1),gamma_val)*num*gm;
  417.       pal[curr].blue  = (p1->blue  == p2->blue ) ? p1->blue  :
  418.           (int) p1->blue  + pow(curr/(double)(num-1),gamma_val)*num*bm;
  419.       }
  420.       }
  421.    }
  422.  
  423.  
  424.  
  425. /*  Swap RG GB & RB columns */
  426.  
  427. static void rotcolrg(PALENTRY pal[], int num)
  428.    {
  429.    int      curr;
  430.    int    dummy;
  431.  
  432.     for (curr=0; curr<=num; curr++)
  433.       {
  434.       dummy = pal[curr].red;
  435.       pal[curr].red = pal[curr].green;
  436.       pal[curr].green = dummy;
  437.       }
  438.    }
  439.  
  440.  
  441. static void rotcolgb(PALENTRY pal[], int num)
  442.    {
  443.    int      curr;
  444.    int    dummy;
  445.  
  446.     for (curr=0; curr<=num; curr++)
  447.       {
  448.       dummy = pal[curr].green;
  449.       pal[curr].green = pal[curr].blue;
  450.       pal[curr].blue = dummy;
  451.       }
  452.    }
  453.  
  454. static void rotcolbr(PALENTRY pal[], int num)
  455.    {
  456.    int      curr;
  457.    int    dummy;
  458.  
  459.     for (curr=0; curr<=num; curr++)
  460.       {
  461.       dummy = pal[curr].red;
  462.       pal[curr].red = pal[curr].blue;
  463.       pal[curr].blue = dummy;
  464.       }
  465.    }
  466.  
  467.  
  468. /*
  469.  * convert a range of colors to grey scale
  470.  */
  471.  
  472.  
  473. static void palrangetogrey(PALENTRY pal[], int first, int how_many)
  474.    {
  475.    PALENTRY      *curr;
  476.    BYTE  val;
  477.  
  478.  
  479.    for (curr = &pal[first]; how_many>0; how_many--, curr++)
  480.       {
  481.       val = (BYTE) ( ((int)curr->red*30 + (int)curr->green*59 + (int)curr->blue*11) / 100 );
  482.       curr->red = curr->green = curr->blue = (BYTE)val;
  483.       }
  484.    }
  485.  
  486. /*
  487.  * convert a range of colors to their inverse
  488.  */
  489.  
  490.  
  491. static void palrangetonegative(PALENTRY pal[], int first, int how_many)
  492.    {
  493.    PALENTRY      *curr;
  494.  
  495.    for (curr = &pal[first]; how_many>0; how_many--, curr++)
  496.       {
  497.       curr->red   = 63 - curr->red;
  498.       curr->green = 63 - curr->green;
  499.       curr->blue  = 63 - curr->blue;
  500.       }
  501.    }
  502.  
  503.  
  504. /*
  505.  * draw and horizontal/vertical dotted lines
  506.  */
  507.  
  508.  
  509. static void hdline(int x, int y, int width)
  510.    {
  511.    int ctr;
  512.    BYTE *ptr;
  513.  
  514.    for (ctr=0, ptr=line_buff; ctr<width; ctr++, ptr++)
  515.       *ptr = (ctr&2) ? bg_color : fg_color;
  516.  
  517.    putrow(x, y, width, (char *)line_buff);
  518.    }
  519.  
  520.  
  521. static void vdline(int x, int y, int depth)
  522.    {
  523.    int ctr;
  524.  
  525.    for (ctr=0; ctr<depth; ctr++, y++)
  526.       clip_putcolor(x, y, (ctr&2) ? bg_color : fg_color);
  527.    }
  528.  
  529.  
  530. static void drect(int x, int y, int width, int depth)
  531.    {
  532.    hdline(x, y, width);
  533.    hdline(x, y+depth-1, width);
  534.  
  535.    vdline(x, y, depth);
  536.    vdline(x+width-1, y, depth);
  537.    }
  538.  
  539.  
  540. /*
  541.  * A very simple memory "allocator".
  542.  *
  543.  * Each call to mem_alloc() returns size bytes from the array mem_block.
  544.  *
  545.  * Be sure to call mem_init() before using mem_alloc()!
  546.  *
  547.  * Uses 4 bytes of DS.
  548.  *
  549.  */
  550.  
  551. static char     *mem_block;
  552. static unsigned  mem_avail;
  553.  
  554.  
  555. static void mem_init(VOIDPTR block, unsigned size)
  556.    {
  557.    mem_block = (char *)block;
  558.    mem_avail = size;
  559.    }
  560.  
  561.  
  562. static VOIDPTR mem_alloc(unsigned size)
  563.    {
  564.    VOIDPTR block;
  565.  
  566.    if (size & 1)
  567.       ++size;   /* allocate even sizes */
  568.  
  569.    if (mem_avail < size)   /* don't let this happen! */
  570.       {
  571.       static char far msg[] = "editpal.c: Out of memory!\n";
  572.  
  573.       stopmsg(0, msg);
  574.       exit(1);
  575.       }
  576.  
  577.    block = mem_block;
  578.    mem_avail -= size;
  579.    mem_block += size;
  580.  
  581.    return(block);
  582.    }
  583.  
  584.  
  585.  
  586. /*
  587.  * misc. routines
  588.  *
  589.  */
  590.  
  591.  
  592. static BOOLEAN is_reserved(int color)
  593.    {
  594.    return ( (reserve_colors && (color==fg_color || color==bg_color) ) ? TRUE : FALSE );
  595.    }
  596.  
  597.  
  598.  
  599. static BOOLEAN is_in_box(int x, int y, int bx, int by, int bw, int bd)
  600.    {
  601.    return ( (x >= bx) && (y >= by) && (x < bx+bw) && (y < by+bd) );
  602.    }
  603.  
  604.  
  605.  
  606. static void draw_diamond(int x, int y, int color)
  607.    {
  608.    putcolor (x+2, y+0,      color);
  609.    hline    (x+1, y+1, 3, color);
  610.    hline    (x+0, y+2, 5, color);
  611.    hline    (x+1, y+3, 3, color);
  612.    putcolor (x+2, y+4,      color);
  613.    }
  614.  
  615.  
  616.  
  617. /*
  618.  * Class:     Cursor
  619.  *
  620.  * Purpose:   Draw the blinking cross-hair cursor.
  621.  *
  622.  * Note:      Only one Cursor can exist (referenced through the_cursor).
  623.  *          IMPORTANT: Call Cursor_Construct before you use any other
  624.  *          Cursor_ function!  Call Cursor_Destroy before exiting to
  625.  *          deallocate memory.
  626.  */
  627.  
  628. struct _Cursor
  629.    {
  630.  
  631.    int       x, y;
  632.    int       hidden;     /* >0 if mouse hidden */
  633.    long    last_blink;
  634.    BOOLEAN blink;
  635.    char    t[CURSOR_SIZE],      /* save line segments here */
  636.        b[CURSOR_SIZE],
  637.        l[CURSOR_SIZE],
  638.        r[CURSOR_SIZE];
  639.    } ;
  640.  
  641. #define Cursor struct _Cursor
  642.  
  643. /* private: */
  644.  
  645.    static  void    Cursor__Draw      (void);
  646.    static  void    Cursor__Save      (void);
  647.    static  void    Cursor__Restore   (void);
  648.  
  649. /* public: */
  650.  
  651.    static  BOOLEAN Cursor_Construct (void);
  652.    static  void    Cursor_Destroy   (void);
  653.  
  654. #ifdef NOT_USED
  655.    static  void    Cursor_SetPos    (int x, int y);
  656.    static  BOOLEAN Cursor_IsHidden  (void);
  657. #endif
  658.    static  void    Cursor_Move        (int xoff, int yoff);
  659.    static  int       Cursor_GetX        (void);
  660.    static  int       Cursor_GetY        (void);
  661.    static  void    Cursor_Hide        (void);
  662.    static  void    Cursor_Show        (void);
  663.  
  664.  
  665. static Cursor *the_cursor = NULL;
  666.  
  667.  
  668. static BOOLEAN Cursor_Construct(void)
  669.    {
  670.    if (the_cursor != NULL)
  671.       return(FALSE);
  672.  
  673.    the_cursor = new(Cursor);
  674.  
  675.    the_cursor->x      = sxdots/2;
  676.    the_cursor->y      = sydots/2;
  677.    the_cursor->hidden      = 1;
  678.    the_cursor->blink      = FALSE;
  679.    the_cursor->last_blink = 0;
  680.  
  681.    return (TRUE);
  682.    }
  683.  
  684.  
  685. static void Cursor_Destroy(void)
  686.    {
  687.    if (the_cursor != NULL)
  688.       delete(the_cursor);
  689.  
  690.    the_cursor = NULL;
  691.    }
  692.  
  693.  
  694.  
  695. static void Cursor__Draw(void)
  696.    {
  697.    int color;
  698.  
  699.    find_special_colors();
  700.    color = (the_cursor->blink) ? color_medium : color_dark;
  701.  
  702.    vline(the_cursor->x, the_cursor->y-CURSOR_SIZE-1, CURSOR_SIZE, color);
  703.    vline(the_cursor->x, the_cursor->y+2,         CURSOR_SIZE, color);
  704.  
  705.    hline(the_cursor->x-CURSOR_SIZE-1, the_cursor->y, CURSOR_SIZE, color);
  706.    hline(the_cursor->x+2,          the_cursor->y, CURSOR_SIZE, color);
  707.    }
  708.  
  709.  
  710. static void Cursor__Save(void)
  711.    {
  712.    vgetrow(the_cursor->x, the_cursor->y-CURSOR_SIZE-1, CURSOR_SIZE, the_cursor->t);
  713.    vgetrow(the_cursor->x, the_cursor->y+2,           CURSOR_SIZE, the_cursor->b);
  714.  
  715.    getrow(the_cursor->x-CURSOR_SIZE-1, the_cursor->y,  CURSOR_SIZE, the_cursor->l);
  716.    getrow(the_cursor->x+2,           the_cursor->y,  CURSOR_SIZE, the_cursor->r);
  717.    }
  718.  
  719.  
  720. static void Cursor__Restore(void)
  721.    {
  722.    vputrow(the_cursor->x, the_cursor->y-CURSOR_SIZE-1, CURSOR_SIZE, the_cursor->t);
  723.    vputrow(the_cursor->x, the_cursor->y+2,           CURSOR_SIZE, the_cursor->b);
  724.  
  725.    putrow(the_cursor->x-CURSOR_SIZE-1, the_cursor->y,  CURSOR_SIZE, the_cursor->l);
  726.    putrow(the_cursor->x+2,           the_cursor->y,  CURSOR_SIZE, the_cursor->r);
  727.    }
  728.  
  729.  
  730.  
  731. #ifdef XFRACT
  732.  
  733. void Cursor_SetPos(int x, int y)
  734.    {
  735.    if (!the_cursor->hidden)
  736.       Cursor__Restore();
  737.  
  738.    the_cursor->x = x;
  739.    the_cursor->y = y;
  740.  
  741.    if (!the_cursor->hidden)
  742.       {
  743.       Cursor__Save();
  744.       Cursor__Draw();
  745.       }
  746.    }
  747.  
  748. #endif
  749.  
  750. #ifdef NOT_USED
  751.  
  752. static int Cursor_IsHidden(void)
  753.    {
  754.    return ( the_cursor->hidden );
  755.    }
  756.  
  757.  
  758. #endif
  759.  
  760.  
  761. static void Cursor_Move(int xoff, int yoff)
  762.    {
  763.    if ( !the_cursor->hidden )
  764.       Cursor__Restore();
  765.  
  766.    the_cursor->x += xoff;
  767.    the_cursor->y += yoff;
  768.  
  769.    if (the_cursor->x < 0)       the_cursor->x = 0;
  770.    if (the_cursor->y < 0)       the_cursor->y = 0;
  771.    if (the_cursor->x >= sxdots) the_cursor->x = sxdots-1;
  772.    if (the_cursor->y >= sydots) the_cursor->y = sydots-1;
  773.  
  774.    if ( !the_cursor->hidden )
  775.       {
  776.       Cursor__Save();
  777.       Cursor__Draw();
  778.       }
  779.    }
  780.  
  781.  
  782. static int Cursor_GetX(void)   { return(the_cursor->x); }
  783.  
  784. static int Cursor_GetY(void)   { return(the_cursor->y); }
  785.  
  786.  
  787. static void Cursor_Hide(void)
  788.    {
  789.    if ( the_cursor->hidden++ == 0 )
  790.       Cursor__Restore();
  791.    }
  792.  
  793.  
  794. static void Cursor_Show(void)
  795.    {
  796.    if ( --the_cursor->hidden == 0)
  797.       {
  798.       Cursor__Save();
  799.       Cursor__Draw();
  800.       }
  801.    }
  802.  
  803.  
  804. static int Cursor_WaitKey(void)   /* blink cursor while waiting for a key */
  805.    {
  806.    long tick;
  807.  
  808. #ifndef XFRACT
  809.    while ( !keypressed() )
  810. #else
  811.    editpal_cursor = 1;
  812.    while ( !waitkeypressed(1) )
  813. #endif
  814.       {
  815.       tick = readticker();
  816.  
  817.       if ( (tick - the_cursor->last_blink) > CURSOR_BLINK_RATE )
  818.      {
  819.      the_cursor->blink = (the_cursor->blink) ? FALSE : TRUE;
  820.      the_cursor->last_blink = tick;
  821.      if ( !the_cursor->hidden )
  822.         Cursor__Draw();
  823.      }
  824.       else if ( tick < the_cursor->last_blink )
  825.      the_cursor->last_blink = tick;
  826.       }
  827.  
  828. #ifdef XFRACT
  829.    editpal_cursor = 0;
  830. #endif
  831.    return( keypressed() );
  832.    }
  833.  
  834.  
  835.  
  836. /*
  837.  * Class:     MoveBox
  838.  *
  839.  * Purpose:   Handles the rectangular move/resize box.
  840.  */
  841.  
  842. struct _MoveBox
  843.    {
  844.    int        x, y;
  845.    int        base_width,
  846.         base_depth;
  847.    int        csize;
  848.    BOOLEAN  moved;
  849.    BOOLEAN  should_hide;
  850.    char    *t, *b,
  851.        *l, *r;
  852.    } ;
  853.  
  854. #define MoveBox struct _MoveBox
  855.  
  856. /* private: */
  857.  
  858.    static void       MoveBox__Draw     (MoveBox *this);
  859.    static void       MoveBox__Erase    (MoveBox *this);
  860.    static void       MoveBox__Move     (MoveBox *this, int key);
  861.  
  862. /* public: */
  863.  
  864.    static MoveBox *MoveBox_Construct  (int x, int y, int csize, int base_width,
  865.                       int base_depth);
  866.    static void       MoveBox_Destroy    (MoveBox *this);
  867.    static BOOLEAN  MoveBox_Process    (MoveBox *this); /* returns FALSE if ESCAPED */
  868.    static BOOLEAN  MoveBox_Moved      (MoveBox *this);
  869.    static BOOLEAN  MoveBox_ShouldHide (MoveBox *this);
  870.    static int       MoveBox_X          (MoveBox *this);
  871.    static int       MoveBox_Y          (MoveBox *this);
  872.    static int       MoveBox_CSize      (MoveBox *this);
  873.  
  874.    static void       MoveBox_SetPos     (MoveBox *this, int x, int y);
  875.    static void       MoveBox_SetCSize   (MoveBox *this, int csize);
  876.  
  877.  
  878.  
  879. static MoveBox *MoveBox_Construct(int x, int y, int csize, int base_width, int base_depth)
  880.    {
  881.    MoveBox *this = new(MoveBox);
  882.  
  883.    this->x         = x;
  884.    this->y         = y;
  885.    this->csize         = csize;
  886.    this->base_width  = base_width;
  887.    this->base_depth  = base_depth;
  888.    this->moved         = FALSE;
  889.    this->should_hide = FALSE;
  890.    this->t         = newx(sxdots);
  891.    this->b         = newx(sxdots);
  892.    this->l         = newx(sydots);
  893.    this->r         = newx(sydots);
  894.  
  895.    return(this);
  896.    }
  897.  
  898.  
  899. static void MoveBox_Destroy(MoveBox *this)
  900.    {
  901.    delete(this->t);
  902.    delete(this->b);
  903.    delete(this->l);
  904.    delete(this->r);
  905.    delete(this);
  906.    }
  907.  
  908.  
  909. static BOOLEAN MoveBox_Moved(MoveBox *this) { return(this->moved); }
  910.  
  911. static BOOLEAN MoveBox_ShouldHide(MoveBox *this) { return(this->should_hide); }
  912.  
  913. static int MoveBox_X(MoveBox *this)     { return(this->x); }
  914.  
  915. static int MoveBox_Y(MoveBox *this)     { return(this->y); }
  916.  
  917. static int MoveBox_CSize(MoveBox *this)  { return(this->csize); }
  918.  
  919.  
  920. static void MoveBox_SetPos(MoveBox *this, int x, int y)
  921.    {
  922.    this->x = x;
  923.    this->y = y;
  924.    }
  925.  
  926.  
  927. static void MoveBox_SetCSize(MoveBox *this, int csize)
  928.    {
  929.    this->csize = csize;
  930.    }
  931.  
  932.  
  933. static void MoveBox__Draw(MoveBox *this)  /* private */
  934.    {
  935.    int width = this->base_width + this->csize*16+1,
  936.        depth = this->base_depth + this->csize*16+1;
  937.    int x     = this->x,
  938.        y     = this->y;
  939.  
  940.  
  941.    getrow (x, y,     width, this->t);
  942.    getrow (x, y+depth-1, width, this->b);
  943.  
  944.    vgetrow(x,          y, depth, this->l);
  945.    vgetrow(x+width-1, y, depth, this->r);
  946.  
  947.    hdline(x, y,         width);
  948.    hdline(x, y+depth-1, width);
  949.  
  950.    vdline(x,         y, depth);
  951.    vdline(x+width-1, y, depth);
  952.    }
  953.  
  954.  
  955. static void MoveBox__Erase(MoveBox *this)   /* private */
  956.    {
  957.    int width = this->base_width + this->csize*16+1,
  958.        depth = this->base_depth + this->csize*16+1;
  959.  
  960.    vputrow(this->x,        this->y, depth, this->l);
  961.    vputrow(this->x+width-1, this->y, depth, this->r);
  962.  
  963.    putrow(this->x, this->y,        width, this->t);
  964.    putrow(this->x, this->y+depth-1, width, this->b);
  965.    }
  966.  
  967.  
  968. #define BOX_INC     1
  969. #define CSIZE_INC   2
  970.  
  971. static void MoveBox__Move(MoveBox *this, int key)
  972.    {
  973.    BOOLEAN done  = FALSE;
  974.    BOOLEAN first = TRUE;
  975.    int       xoff  = 0,
  976.        yoff  = 0;
  977.  
  978.    while ( !done )
  979.       {
  980.       switch(key)
  981.      {
  982.      case RIGHT_ARROW_2:     xoff += BOX_INC*4;   break;
  983.      case RIGHT_ARROW:     xoff += BOX_INC;     break;
  984.      case LEFT_ARROW_2:     xoff -= BOX_INC*4;   break;
  985.      case LEFT_ARROW:     xoff -= BOX_INC;     break;
  986.      case DOWN_ARROW_2:     yoff += BOX_INC*4;   break;
  987.      case DOWN_ARROW:     yoff += BOX_INC;     break;
  988.      case UP_ARROW_2:     yoff -= BOX_INC*4;   break;
  989.      case UP_ARROW:      yoff -= BOX_INC;     break;
  990.  
  991.      default:
  992.         done = TRUE;
  993.      }
  994.  
  995.       if (!done)
  996.      {
  997.      if (!first)
  998.         getakey();         /* delete key from buffer */
  999.      else
  1000.         first = FALSE;
  1001.      key = keypressed();   /* peek at the next one... */
  1002.      }
  1003.       }
  1004.  
  1005.    xoff += this->x;
  1006.    yoff += this->y;   /* (xoff,yoff) = new position */
  1007.  
  1008.    if (xoff < 0) xoff = 0;
  1009.    if (yoff < 0) yoff = 0;
  1010.  
  1011.    if (xoff+this->base_width+this->csize*16+1 > sxdots)
  1012.        xoff = sxdots - (this->base_width+this->csize*16+1);
  1013.  
  1014.    if (yoff+this->base_depth+this->csize*16+1 > sydots)
  1015.       yoff = sydots - (this->base_depth+this->csize*16+1);
  1016.  
  1017.    if ( xoff!=this->x || yoff!=this->y )
  1018.       {
  1019.       MoveBox__Erase(this);
  1020.       this->y = yoff;
  1021.       this->x = xoff;
  1022.       MoveBox__Draw(this);
  1023.       }
  1024.    }
  1025.  
  1026.  
  1027. static BOOLEAN MoveBox_Process(MoveBox *this)
  1028.    {
  1029.    int       key;
  1030.    int       orig_x     = this->x,
  1031.        orig_y     = this->y,
  1032.        orig_csize = this->csize;
  1033.  
  1034.    MoveBox__Draw(this);
  1035.  
  1036.    while (1)
  1037.       {
  1038.       Cursor_WaitKey();
  1039.       key = getakey();
  1040.  
  1041.       if (key==ENTER || key==ENTER_2 || key==ESC || key=='H' || key=='h')
  1042.      {
  1043.      if (this->x != orig_x || this->y != orig_y || this->csize != orig_csize)
  1044.         this->moved = TRUE;
  1045.      else
  1046.        this->moved = FALSE;
  1047.      break;
  1048.      }
  1049.  
  1050.       switch(key)
  1051.      {
  1052.      case UP_ARROW:
  1053.      case DOWN_ARROW:
  1054.      case LEFT_ARROW:
  1055.      case RIGHT_ARROW:
  1056.      case UP_ARROW_2:
  1057.      case DOWN_ARROW_2:
  1058.      case LEFT_ARROW_2:
  1059.      case RIGHT_ARROW_2:
  1060.         MoveBox__Move(this, key);
  1061.         break;
  1062.  
  1063.      case PAGE_UP:     /* shrink */
  1064.         if (this->csize > CSIZE_MIN)
  1065.            {
  1066.            int t = this->csize - CSIZE_INC;
  1067.            int change;
  1068.  
  1069.            if (t < CSIZE_MIN)
  1070.           t = CSIZE_MIN;
  1071.  
  1072.            MoveBox__Erase(this);
  1073.  
  1074.            change = this->csize - t;
  1075.            this->csize = t;
  1076.            this->x += (change*16) / 2;
  1077.            this->y += (change*16) / 2;
  1078.            MoveBox__Draw(this);
  1079.            }
  1080.         break;
  1081.  
  1082.      case PAGE_DOWN:   /* grow */
  1083.         {
  1084.         int max_width = min(sxdots, MAX_WIDTH);
  1085.  
  1086.         if (this->base_depth+(this->csize+CSIZE_INC)*16+1 < sydots  &&
  1087.             this->base_width+(this->csize+CSIZE_INC)*16+1 < max_width )
  1088.            {
  1089.            MoveBox__Erase(this);
  1090.            this->x -= (CSIZE_INC*16) / 2;
  1091.            this->y -= (CSIZE_INC*16) / 2;
  1092.            this->csize += CSIZE_INC;
  1093.            if (this->y+this->base_depth+this->csize*16+1 > sydots)
  1094.           this->y = sydots - (this->base_depth+this->csize*16+1);
  1095.            if (this->x+this->base_width+this->csize*16+1 > max_width)
  1096.           this->x = max_width - (this->base_width+this->csize*16+1);
  1097.            if (this->y < 0)
  1098.           this->y = 0;
  1099.            if (this->x < 0)
  1100.           this->x = 0;
  1101.            MoveBox__Draw(this);
  1102.            }
  1103.         }
  1104.         break;
  1105.      }
  1106.       }
  1107.  
  1108.    MoveBox__Erase(this);
  1109.  
  1110.    this->should_hide = (key == 'H' || key == 'h') ? TRUE : FALSE;
  1111.  
  1112.    return( (key==ESC) ? FALSE : TRUE );
  1113.    }
  1114.  
  1115.  
  1116.  
  1117. /*
  1118.  * Class:     CEditor
  1119.  *
  1120.  * Purpose:   Edits a single color component (R, G or B)
  1121.  *
  1122.  * Note:      Calls the "other_key" function to process keys it doesn't use.
  1123.  *          The "change" function is called whenever the value is changed
  1124.  *          by the CEditor.
  1125.  */
  1126.  
  1127. struct _CEditor
  1128.    {
  1129.    int         x, y;
  1130.    char      letter;
  1131.    int         val;
  1132.    BOOLEAN   done;
  1133.    BOOLEAN   hidden;
  1134. #ifndef XFRACT
  1135.    void    (*other_key)(int key, struct _CEditor *ce, VOIDPTR info);
  1136.    void    (*change)(struct _CEditor *ce, VOIDPTR info);
  1137. #else
  1138.    void    (*other_key)();
  1139.    void    (*change)();
  1140. #endif
  1141.    void     *info;
  1142.  
  1143.    } ;
  1144.  
  1145. #define CEditor struct _CEditor
  1146.  
  1147. /* public: */
  1148.  
  1149. #ifndef XFRACT
  1150.    static CEditor *CEditor_Construct( int x, int y, char letter,
  1151.                       void (*other_key)(int,CEditor*,void*),
  1152.                                       void (*change)(CEditor*,void*), VOIDPTR info);
  1153.    static void CEditor_Destroy     (CEditor *this);
  1154.    static void CEditor_Draw     (CEditor *this);
  1155.    static void CEditor_SetPos     (CEditor *this, int x, int y);
  1156.    static void CEditor_SetVal     (CEditor *this, int val);
  1157.    static int  CEditor_GetVal     (CEditor *this);
  1158.    static void CEditor_SetDone     (CEditor *this, BOOLEAN done);
  1159.    static void CEditor_SetHidden (CEditor *this, BOOLEAN hidden);
  1160.    static int  CEditor_Edit     (CEditor *this);
  1161. #else
  1162.    static CEditor *CEditor_Construct( int , int , char ,
  1163.                                     void (*other_key)(),
  1164.                                     void (*change)(), VOIDPTR );
  1165.    static void CEditor_Destroy         (CEditor *);
  1166.    static void CEditor_Draw    (CEditor *);
  1167.    static void CEditor_SetPos  (CEditor *, int , int );
  1168.    static void CEditor_SetVal  (CEditor *, int );
  1169.    static int  CEditor_GetVal  (CEditor *);
  1170.    static void CEditor_SetDone         (CEditor *, BOOLEAN );
  1171.    static void CEditor_SetHidden (CEditor *, BOOLEAN );
  1172.    static int  CEditor_Edit    (CEditor *);
  1173. #endif
  1174.  
  1175. #define CEditor_WIDTH (8*3+4)
  1176. #define CEditor_DEPTH (8+4)
  1177.  
  1178.  
  1179.  
  1180. #ifndef XFRACT
  1181. static CEditor *CEditor_Construct( int x, int y, char letter,
  1182.                    void (*other_key)(int,CEditor*,VOIDPTR),
  1183.                    void (*change)(CEditor*, VOIDPTR), VOIDPTR info)
  1184. #else
  1185. static CEditor *CEditor_Construct( int x, int y, char letter,
  1186.                                    void (*other_key)(),
  1187.                                    void (*change)(), VOIDPTR info)
  1188. #endif
  1189.    {
  1190.    CEditor *this = new(CEditor);
  1191.  
  1192.    this->x       = x;
  1193.    this->y       = y;
  1194.    this->letter    = letter;
  1195.    this->val       = 0;
  1196.    this->other_key = other_key;
  1197.    this->hidden    = FALSE;
  1198.    this->change    = change;
  1199.    this->info       = info;
  1200.  
  1201.    return(this);
  1202.    }
  1203.  
  1204.  
  1205. static void CEditor_Destroy(CEditor *this)
  1206.    {
  1207.    delete(this);
  1208.    }
  1209.  
  1210.  
  1211. static void CEditor_Draw(CEditor *this)
  1212.    {
  1213.    if (this->hidden)
  1214.       return;
  1215.  
  1216.    Cursor_Hide();
  1217.    displayf(this->x+2, this->y+2, fg_color, bg_color, "%c%02d", this->letter, this->val);
  1218.    Cursor_Show();
  1219.    }
  1220.  
  1221.  
  1222. static void CEditor_SetPos(CEditor *this, int x, int y)
  1223.    {
  1224.    this->x = x;
  1225.    this->y = y;
  1226.    }
  1227.  
  1228.  
  1229. static void CEditor_SetVal(CEditor *this, int val)
  1230.    {
  1231.    this->val = val;
  1232.    }
  1233.  
  1234.  
  1235. static int CEditor_GetVal(CEditor *this)
  1236.    {
  1237.    return(this->val);
  1238.    }
  1239.  
  1240.  
  1241. static void CEditor_SetDone(CEditor *this, BOOLEAN done)
  1242.    {
  1243.    this->done = done;
  1244.    }
  1245.  
  1246.  
  1247. static void CEditor_SetHidden(CEditor *this, BOOLEAN hidden)
  1248.    {
  1249.    this->hidden = hidden;
  1250.    }
  1251.  
  1252.  
  1253. static int CEditor_Edit(CEditor *this)
  1254.    {
  1255.    int key;
  1256.    int diff;   /* <EAN> */
  1257.  
  1258.    this->done = FALSE;
  1259.  
  1260.    if (!this->hidden)
  1261.       {
  1262.       Cursor_Hide();
  1263.       rect(this->x, this->y, CEditor_WIDTH, CEditor_DEPTH, fg_color);
  1264.       Cursor_Show();
  1265.       }
  1266.  
  1267.    while ( !this->done )
  1268.       {
  1269.       Cursor_WaitKey();
  1270.       key = getakey();
  1271.  
  1272.       switch( key )
  1273.      {
  1274.      case PAGE_UP:
  1275.         if (this->val < 63)
  1276.            {
  1277.            this->val += 5;
  1278.            if (this->val > 63)
  1279.           this->val = 63;
  1280.            CEditor_Draw(this);
  1281.            this->change(this, this->info);
  1282.            }
  1283.         break;
  1284.  
  1285.      case '+':
  1286.         diff = 1;
  1287.         while ( keypressed() == key )
  1288.            {
  1289.            getakey();
  1290.            ++diff;
  1291.            }
  1292.         if (this->val < 63)
  1293.            {
  1294.            this->val += diff;
  1295.            if (this->val > 63)
  1296.           this->val = 63;
  1297.            CEditor_Draw(this);
  1298.            this->change(this, this->info);
  1299.            }
  1300.         break;
  1301.  
  1302.      case PAGE_DOWN:
  1303.         if (this->val > 0)
  1304.            {
  1305.            this->val -= 5;
  1306.            if (this->val < 0)
  1307.           this->val = 0;
  1308.            CEditor_Draw(this);
  1309.            this->change(this, this->info);
  1310.            } break;
  1311.  
  1312.      case '-':
  1313.         diff = 1;
  1314.         while ( keypressed() == key )
  1315.            {
  1316.            getakey();
  1317.            ++diff;
  1318.            }
  1319.         if (this->val > 0)
  1320.            {
  1321.            this->val -= diff;
  1322.            if (this->val < 0)
  1323.           this->val = 0;
  1324.            CEditor_Draw(this);
  1325.            this->change(this, this->info);
  1326.            }
  1327.         break;
  1328.  
  1329.      case '0':
  1330.      case '1':
  1331.      case '2':
  1332.      case '3':
  1333.      case '4':
  1334.      case '5':
  1335.      case '6':
  1336.      case '7':
  1337.      case '8':
  1338.      case '9':
  1339.         this->val = (key - '0') * 10;
  1340.         if (this->val > 63)
  1341.            this->val = 63;
  1342.         CEditor_Draw(this);
  1343.         this->change(this, this->info);
  1344.         break;
  1345.  
  1346.      default:
  1347.         this->other_key(key, this, this->info);
  1348.         break;
  1349.      } /* switch */
  1350.       } /* while */
  1351.  
  1352.    if (!this->hidden)
  1353.       {
  1354.       Cursor_Hide();
  1355.       rect(this->x, this->y, CEditor_WIDTH, CEditor_DEPTH, bg_color);
  1356.       Cursor_Show();
  1357.       }
  1358.  
  1359.    return(key);
  1360.    }
  1361.  
  1362.  
  1363.  
  1364. /*
  1365.  * Class:     RGBEditor
  1366.  *
  1367.  * Purpose:   Edits a complete color using three CEditors for R, G and B
  1368.  */
  1369.  
  1370. struct _RGBEditor
  1371.    {
  1372.    int         x, y;          /* position */
  1373.    int         curr;          /* 0=r, 1=g, 2=b */
  1374.    int         pal;          /* palette number */
  1375.    BOOLEAN   done;
  1376.    BOOLEAN   hidden;
  1377.    CEditor  *color[3];          /* color editors 0=r, 1=g, 2=b */
  1378. #ifndef XFRACT
  1379.    void    (*other_key)(int key, struct _RGBEditor *e, VOIDPTR info);
  1380.    void    (*change)(struct _RGBEditor *e, VOIDPTR info);
  1381. #else
  1382.    void    (*other_key)();
  1383.    void    (*change)();
  1384. #endif
  1385.    void     *info;
  1386.    } ;
  1387.  
  1388. #define RGBEditor struct _RGBEditor
  1389.  
  1390. /* private: */
  1391.  
  1392.    static void      RGBEditor__other_key (int key, CEditor *ceditor, VOIDPTR info);
  1393.    static void      RGBEditor__change    (CEditor *ceditor, VOIDPTR info);
  1394.  
  1395. /* public: */
  1396.  
  1397. #ifndef XFRACT
  1398.    static RGBEditor *RGBEditor_Construct(int x, int y,
  1399.              void (*other_key)(int,RGBEditor*,void*),
  1400.              void (*change)(RGBEditor*,void*), VOIDPTR info);
  1401. #else
  1402.    static RGBEditor *RGBEditor_Construct(int x, int y,
  1403.                      void (*other_key)(),
  1404.                      void (*change)(), VOIDPTR info);
  1405. #endif
  1406.             
  1407.    static void       RGBEditor_Destroy  (RGBEditor *this);
  1408.    static void       RGBEditor_SetPos   (RGBEditor *this, int x, int y);
  1409.    static void       RGBEditor_SetDone  (RGBEditor *this, BOOLEAN done);
  1410.    static void       RGBEditor_SetHidden(RGBEditor *this, BOOLEAN hidden);
  1411.    static void       RGBEditor_BlankSampleBox(RGBEditor *this);
  1412.    static void       RGBEditor_Update   (RGBEditor *this);
  1413.    static void       RGBEditor_Draw     (RGBEditor *this);
  1414.    static int       RGBEditor_Edit     (RGBEditor *this);
  1415.    static void       RGBEditor_SetRGB   (RGBEditor *this, int pal, PALENTRY *rgb);
  1416.    static PALENTRY RGBEditor_GetRGB   (RGBEditor *this);
  1417.  
  1418. #define RGBEditor_WIDTH 62
  1419. #define RGBEditor_DEPTH (1+1+CEditor_DEPTH*3-2+2)
  1420.  
  1421. #define RGBEditor_BWIDTH ( RGBEditor_WIDTH - (2+CEditor_WIDTH+1 + 2) )
  1422. #define RGBEditor_BDEPTH ( RGBEditor_DEPTH - 4 )
  1423.  
  1424.  
  1425.  
  1426. #ifndef XFRACT
  1427. static RGBEditor *RGBEditor_Construct(int x, int y, void (*other_key)(int,RGBEditor*,void*),
  1428.                       void (*change)(RGBEditor*,void*), VOIDPTR info)
  1429. #else
  1430. static RGBEditor *RGBEditor_Construct(int x, int y, void (*other_key)(),
  1431.                                       void (*change)(), VOIDPTR info)
  1432. #endif
  1433.    {
  1434.    RGBEditor      *this     = new(RGBEditor);
  1435.    static char far letter[] = "RGB";
  1436.    int           ctr;
  1437.  
  1438.    for (ctr=0; ctr<3; ctr++)
  1439.       this->color[ctr] = CEditor_Construct(0, 0, letter[ctr], RGBEditor__other_key,
  1440.                        RGBEditor__change, this);
  1441.  
  1442.    RGBEditor_SetPos(this, x, y);
  1443.    this->curr       = 0;
  1444.    this->pal       = 1;
  1445.    this->hidden    = FALSE;
  1446.    this->other_key = other_key;
  1447.    this->change    = change;
  1448.    this->info       = info;
  1449.  
  1450.    return(this);
  1451.    }
  1452.  
  1453.  
  1454. static void RGBEditor_Destroy(RGBEditor *this)
  1455.    {
  1456.    CEditor_Destroy(this->color[0]);
  1457.    CEditor_Destroy(this->color[1]);
  1458.    CEditor_Destroy(this->color[2]);
  1459.    delete(this);
  1460.    }
  1461.  
  1462.  
  1463. static void RGBEditor_SetDone(RGBEditor *this, BOOLEAN done)
  1464.    {
  1465.    this->done = done;
  1466.    }
  1467.  
  1468.  
  1469. static void RGBEditor_SetHidden(RGBEditor *this, BOOLEAN hidden)
  1470.    {
  1471.    this->hidden = hidden;
  1472.    CEditor_SetHidden(this->color[0], hidden);
  1473.    CEditor_SetHidden(this->color[1], hidden);
  1474.    CEditor_SetHidden(this->color[2], hidden);
  1475.    }
  1476.  
  1477.  
  1478. static void RGBEditor__other_key(int key, CEditor *ceditor, VOIDPTR info) /* private */
  1479.    {
  1480.    RGBEditor *this = (RGBEditor *)info;
  1481.  
  1482.    switch( key )
  1483.       {
  1484.       case 'R':
  1485.       case 'r':
  1486.      if (this->curr != 0)
  1487.         {
  1488.         this->curr = 0;
  1489.         CEditor_SetDone(ceditor, TRUE);
  1490.         }
  1491.      break;
  1492.  
  1493.       case 'G':
  1494.       case 'g':
  1495.      if (this->curr != 1)
  1496.         {
  1497.         this->curr = 1;
  1498.         CEditor_SetDone(ceditor, TRUE);
  1499.         }
  1500.      break;
  1501.  
  1502.       case 'B':
  1503.       case 'b':
  1504.      if (this->curr != 2)
  1505.         {
  1506.         this->curr = 2;
  1507.         CEditor_SetDone(ceditor, TRUE);
  1508.         }
  1509.      break;
  1510.  
  1511.       case DELETE:   /* move to next CEditor */
  1512.      if ( ++this->curr > 2)
  1513.         this->curr = 0;
  1514.      CEditor_SetDone(ceditor, TRUE);
  1515.      break;
  1516.  
  1517.       case INSERT:   /* move to prev CEditor */
  1518.      if ( --this->curr < 0)
  1519.         this->curr = 2;
  1520.      CEditor_SetDone(ceditor, TRUE);
  1521.      break;
  1522.  
  1523.       default:
  1524.      this->other_key(key, this, this->info);
  1525.      if (this->done)
  1526.         CEditor_SetDone(ceditor, TRUE);
  1527.      break;
  1528.       }
  1529.    }
  1530.  
  1531.  
  1532.  
  1533. #ifdef __TURBOC__
  1534. #   pragma argsused   /* kills "arg not used" warning */
  1535. #endif
  1536.  
  1537. static void RGBEditor__change(CEditor *ceditor, VOIDPTR info) /* private */
  1538.    {
  1539.    RGBEditor *this = (RGBEditor *)info;
  1540.  
  1541.    if ( this->pal < colors && !is_reserved(this->pal) )
  1542.       setpal(this->pal, CEditor_GetVal(this->color[0]),
  1543.       CEditor_GetVal(this->color[1]), CEditor_GetVal(this->color[2]));
  1544.  
  1545.    this->change(this, this->info);
  1546.    }
  1547.  
  1548.  
  1549. static void RGBEditor_SetPos(RGBEditor *this, int x, int y)
  1550.    {
  1551.    this->x = x;
  1552.    this->y = y;
  1553.  
  1554.    CEditor_SetPos(this->color[0], x+2, y+2);
  1555.    CEditor_SetPos(this->color[1], x+2, y+2+CEditor_DEPTH-1);
  1556.    CEditor_SetPos(this->color[2], x+2, y+2+CEditor_DEPTH-1+CEditor_DEPTH-1);
  1557.    }
  1558.  
  1559.  
  1560. static void RGBEditor_BlankSampleBox(RGBEditor *this)
  1561.    {
  1562.    if (this->hidden)
  1563.       return ;
  1564.  
  1565.    Cursor_Hide();
  1566.    fillrect(this->x+2+CEditor_WIDTH+1+1, this->y+2+1, RGBEditor_BWIDTH-2, RGBEditor_BDEPTH-2, bg_color);
  1567.    Cursor_Show();
  1568.    }
  1569.  
  1570.  
  1571. static void RGBEditor_Update(RGBEditor *this)
  1572.    {
  1573.    int x1 = this->x+2+CEditor_WIDTH+1+1,
  1574.        y1 = this->y+2+1;
  1575.  
  1576.    if (this->hidden)
  1577.       return ;
  1578.  
  1579.    Cursor_Hide();
  1580.  
  1581.    if ( this->pal >= colors )
  1582.       {
  1583.       fillrect(x1, y1, RGBEditor_BWIDTH-2, RGBEditor_BDEPTH-2, bg_color);
  1584.       draw_diamond(x1+(RGBEditor_BWIDTH-5)/2, y1+(RGBEditor_BDEPTH-5)/2, fg_color);
  1585.       }
  1586.  
  1587.    else if ( is_reserved(this->pal) )
  1588.       {
  1589.       int x2 = x1+RGBEditor_BWIDTH-3,
  1590.       y2 = y1+RGBEditor_BDEPTH-3;
  1591.  
  1592.       fillrect(x1, y1, RGBEditor_BWIDTH-2, RGBEditor_BDEPTH-2, bg_color);
  1593.       draw_line(x1, y1, x2, y2, fg_color);
  1594.       draw_line(x1, y2, x2, y1, fg_color);
  1595.       }
  1596.    else
  1597.       fillrect(x1, y1, RGBEditor_BWIDTH-2, RGBEditor_BDEPTH-2, this->pal);
  1598.  
  1599.    CEditor_Draw(this->color[0]);
  1600.    CEditor_Draw(this->color[1]);
  1601.    CEditor_Draw(this->color[2]);
  1602.    Cursor_Show();
  1603.    }
  1604.  
  1605.  
  1606. static void RGBEditor_Draw(RGBEditor *this)
  1607.    {
  1608.    if (this->hidden)
  1609.       return ;
  1610.  
  1611.    Cursor_Hide();
  1612.    drect(this->x, this->y, RGBEditor_WIDTH, RGBEditor_DEPTH);
  1613.    fillrect(this->x+1, this->y+1, RGBEditor_WIDTH-2, RGBEditor_DEPTH-2, bg_color);
  1614.    rect(this->x+1+CEditor_WIDTH+2, this->y+2, RGBEditor_BWIDTH, RGBEditor_BDEPTH, fg_color);
  1615.    RGBEditor_Update(this);
  1616.    Cursor_Show();
  1617.    }
  1618.  
  1619.  
  1620. static int RGBEditor_Edit(RGBEditor *this)
  1621.    {
  1622.    int key;
  1623.  
  1624.    this->done = FALSE;
  1625.  
  1626.    if (!this->hidden)
  1627.       {
  1628.       Cursor_Hide();
  1629.       rect(this->x, this->y, RGBEditor_WIDTH, RGBEditor_DEPTH, fg_color);
  1630.       Cursor_Show();
  1631.       }
  1632.  
  1633.    while ( !this->done )
  1634.       key = CEditor_Edit( this->color[this->curr] );
  1635.  
  1636.    if (!this->hidden)
  1637.       {
  1638.       Cursor_Hide();
  1639.       drect(this->x, this->y, RGBEditor_WIDTH, RGBEditor_DEPTH);
  1640.       Cursor_Show();
  1641.       }
  1642.  
  1643.    return (key);
  1644.    }
  1645.  
  1646.  
  1647. static void RGBEditor_SetRGB(RGBEditor *this, int pal, PALENTRY *rgb)
  1648.    {
  1649.    this->pal = pal;
  1650.    CEditor_SetVal(this->color[0], rgb->red);
  1651.    CEditor_SetVal(this->color[1], rgb->green);
  1652.    CEditor_SetVal(this->color[2], rgb->blue);
  1653.    }
  1654.  
  1655.  
  1656. static PALENTRY RGBEditor_GetRGB(RGBEditor *this)
  1657.    {
  1658.    PALENTRY pal;
  1659.  
  1660.    pal.red   = CEditor_GetVal(this->color[0]);
  1661.    pal.green = CEditor_GetVal(this->color[1]);
  1662.    pal.blue  = CEditor_GetVal(this->color[2]);
  1663.  
  1664.    return(pal);
  1665.    }
  1666.  
  1667.  
  1668.  
  1669. /*
  1670.  * Class:     PalTable
  1671.  *
  1672.  * Purpose:   This is where it all comes together.  Creates the two RGBEditors
  1673.  *          and the palette. Moves the cursor, hides/restores the screen,
  1674.  *          handles (S)hading, (C)opying, e(X)clude mode, the "Y" exclusion
  1675.  *          mode, (Z)oom option, (H)ide palette, rotation, etc.
  1676.  *
  1677.  */
  1678.  
  1679. enum stored_at_values
  1680.    {
  1681.    NOWHERE,
  1682.    DISK,
  1683.    MEMORY
  1684.    } ;
  1685.  
  1686. struct  _PalTable
  1687.    {
  1688.    int         x, y;
  1689.    int         csize;
  1690.    int         active;   /* which RGBEditor is active (0,1) */
  1691.    int         curr[2];
  1692.    RGBEditor    *rgb[2];
  1693.    MoveBox      *movebox;
  1694.    BOOLEAN     done;
  1695.    BOOLEAN     exclude;
  1696.    BOOLEAN     auto_select;
  1697.    PALENTRY     pal[256];
  1698.    int         hidden;
  1699.  
  1700.    int         stored_at;
  1701.    FILE         *file;
  1702.    char far     *memory;
  1703.  
  1704.    PALENTRY far *save_pal[8];
  1705.    } ;
  1706.  
  1707. #define PalTable struct _PalTable
  1708.  
  1709. /* private: */
  1710.  
  1711.    static void      PalTable__HlPal       (PalTable *this, int pnum, int color);
  1712.    static void      PalTable__Draw        (PalTable *this);
  1713.    static BOOLEAN PalTable__SetCurr     (PalTable *this, int which, int curr);
  1714.    static BOOLEAN PalTable__MemoryAlloc (PalTable *this, long size);
  1715.    static void      PalTable__SaveRect    (PalTable *this);
  1716.    static void      PalTable__RestoreRect (PalTable *this);
  1717.    static void      PalTable__SetPos      (PalTable *this, int x, int y);
  1718.    static void      PalTable__SetCSize    (PalTable *this, int csize);
  1719.    static int      PalTable__GetCursorColor(PalTable *this);
  1720.    static void      PalTable__DoCurs      (PalTable *this, int key);
  1721.    static void      PalTable__Rotate      (PalTable *this, int dir);
  1722.    static void      PalTable__UpdateDAC   (PalTable *this);
  1723.    static void    PalTable__other_key   (int key, RGBEditor *rgb, VOIDPTR info);
  1724.    static void    PalTable__change      (RGBEditor *rgb, VOIDPTR info);
  1725.  
  1726. /* public: */
  1727.  
  1728.    static PalTable *PalTable_Construct (void);
  1729.    static void        PalTable_Destroy   (PalTable *this);
  1730.    static void        PalTable_Process   (PalTable *this);
  1731.    static void        PalTable_SetHidden (PalTable *this, BOOLEAN hidden);
  1732.    static void        PalTable_Hide      (PalTable *this, RGBEditor *rgb, BOOLEAN hidden);
  1733.  
  1734.  
  1735. #define PalTable_PALX (1)
  1736. #define PalTable_PALY (2+RGBEditor_DEPTH+2)
  1737.  
  1738.  
  1739. static void PalTable__HlPal(PalTable *this, int pnum, int color)
  1740.    {
  1741.    int x    = this->x + PalTable_PALX + (pnum%16)*this->csize,
  1742.        y    = this->y + PalTable_PALY + (pnum/16)*this->csize,
  1743.        size = this->csize;
  1744.  
  1745.    if (this->hidden)
  1746.       return ;
  1747.  
  1748.    Cursor_Hide();
  1749.  
  1750.    if (color < 0)
  1751.       drect(x, y, size+1, size+1);
  1752.    else
  1753.       rect(x, y, size+1, size+1, color);
  1754.  
  1755.    Cursor_Show();
  1756.    }
  1757.  
  1758.  
  1759. static void PalTable__Draw(PalTable *this)
  1760.    {
  1761.    int pal;
  1762.    int xoff, yoff;
  1763.    int width;
  1764.  
  1765.    if (this->hidden)
  1766.       return ;
  1767.  
  1768.    Cursor_Hide();
  1769.  
  1770.    width = 1+(this->csize*16)+1+1;
  1771.  
  1772.    rect(this->x, this->y, width, 2+RGBEditor_DEPTH+2+(this->csize*16)+1+1, fg_color);
  1773.  
  1774.    fillrect(this->x+1, this->y+1, width-2, 2+RGBEditor_DEPTH+2+(this->csize*16)+1+1-2, bg_color);
  1775.  
  1776.    hline(this->x, this->y+PalTable_PALY-1, width, fg_color);
  1777.  
  1778.    if ( width - (RGBEditor_WIDTH*2+4) >= TITLE_LEN*8 )
  1779.       {
  1780.       int center = (width - TITLE_LEN*8) / 2;
  1781.  
  1782.       displayf(this->x+center, this->y+2+RGBEditor_DEPTH/2-4, fg_color, bg_color, TITLE);
  1783.       }
  1784.  
  1785.    RGBEditor_Draw(this->rgb[0]);
  1786.    RGBEditor_Draw(this->rgb[1]);
  1787.  
  1788.    for (pal=0; pal<256; pal++)
  1789.       {
  1790.       xoff = PalTable_PALX + (pal%16) * this->csize;
  1791.       yoff = PalTable_PALY + (pal/16) * this->csize;
  1792.  
  1793.       if ( pal >= colors )
  1794.      {
  1795.      fillrect(this->x + xoff + 1, this->y + yoff + 1, this->csize-1, this->csize-1, bg_color);
  1796.      draw_diamond(this->x + xoff + this->csize/2 - 1, this->y + yoff + this->csize/2 - 1, fg_color);
  1797.      }
  1798.  
  1799.       else if ( is_reserved(pal) )
  1800.      {
  1801.      int x1 = this->x + xoff + 1,
  1802.          y1 = this->y + yoff + 1,
  1803.          x2 = x1 + this->csize - 2,
  1804.          y2 = y1 + this->csize - 2;
  1805.      fillrect(this->x + xoff + 1, this->y + yoff + 1, this->csize-1, this->csize-1, bg_color);
  1806.      draw_line(x1, y1, x2, y2, fg_color);
  1807.      draw_line(x1, y2, x2, y1, fg_color);
  1808.      }
  1809.       else
  1810.      fillrect(this->x + xoff + 1, this->y + yoff + 1, this->csize-1, this->csize-1, pal);
  1811.  
  1812.       }
  1813.  
  1814.    if (this->active == 0)
  1815.       {
  1816.       PalTable__HlPal(this, this->curr[1], -1);
  1817.       PalTable__HlPal(this, this->curr[0], fg_color);
  1818.       }
  1819.    else
  1820.       {
  1821.       PalTable__HlPal(this, this->curr[0], -1);
  1822.       PalTable__HlPal(this, this->curr[1], fg_color);
  1823.       }
  1824.  
  1825.    Cursor_Show();
  1826.    }
  1827.  
  1828.  
  1829.  
  1830. static BOOLEAN PalTable__SetCurr(PalTable *this, int which, int curr)
  1831.    {
  1832.    BOOLEAN redraw = (which < 0) ? TRUE : FALSE;
  1833.  
  1834.    if ( redraw )
  1835.       {
  1836.       which = this->active;
  1837.       curr = this->curr[which];
  1838.       }
  1839.    else
  1840.       if ( curr == this->curr[which] || curr < 0 )
  1841.      return (FALSE);
  1842.  
  1843.    Cursor_Hide();
  1844.  
  1845.    PalTable__HlPal(this, this->curr[0], bg_color);
  1846.    PalTable__HlPal(this, this->curr[1], bg_color);
  1847.  
  1848.    this->curr[which] = curr;
  1849.  
  1850.    if (this->curr[0] != this->curr[1])
  1851.       PalTable__HlPal(this, this->curr[this->active==0?1:0], -1);
  1852.    PalTable__HlPal(this, this->curr[this->active], fg_color);
  1853.  
  1854.    RGBEditor_SetRGB(this->rgb[which], this->curr[which], &(this->pal[this->curr[which]]));
  1855.  
  1856.    if (redraw)
  1857.       {
  1858.       int other = (which==0) ? 1 : 0;
  1859.       RGBEditor_SetRGB(this->rgb[other], this->curr[other], &(this->pal[this->curr[other]]));
  1860.       RGBEditor_Update(this->rgb[0]);
  1861.       RGBEditor_Update(this->rgb[1]);
  1862.       }
  1863.    else
  1864.       RGBEditor_Update(this->rgb[which]);
  1865.  
  1866.    if (this->exclude)
  1867.       PalTable__UpdateDAC(this);
  1868.  
  1869.    Cursor_Show();
  1870.  
  1871.    return(TRUE);
  1872.    }
  1873.  
  1874.  
  1875. static BOOLEAN PalTable__MemoryAlloc(PalTable *this, long size)
  1876.    {
  1877.    char far *temp;
  1878.  
  1879.    temp = farmemalloc(FAR_RESERVE);   /* minimum free space */
  1880.  
  1881.    if (temp == NULL)
  1882.       {
  1883.       this->stored_at = NOWHERE;
  1884.       return (FALSE);   /* can't do it */
  1885.       }
  1886.  
  1887.    this->memory = farmemalloc( size );
  1888.  
  1889.    farmemfree(temp);
  1890.  
  1891.    if ( this->memory == NULL )
  1892.       {
  1893.       this->stored_at = NOWHERE;
  1894.       return (FALSE);
  1895.       }
  1896.    else
  1897.       {
  1898.       this->stored_at = MEMORY;
  1899.       return (TRUE);
  1900.       }
  1901.    }
  1902.  
  1903.  
  1904. static void PalTable__SaveRect(PalTable *this)
  1905.    {
  1906.    char buff[MAX_WIDTH];
  1907.    int  width = PalTable_PALX + this->csize*16 + 1 + 1,
  1908.         depth = PalTable_PALY + this->csize*16 + 1 + 1;
  1909.    int  yoff;
  1910.  
  1911.  
  1912.    /* first, do any de-allocationg */
  1913.  
  1914.    switch( this->stored_at )
  1915.       {
  1916.       case NOWHERE:
  1917.      break;
  1918.  
  1919.       case DISK:
  1920.      break;
  1921.  
  1922.       case MEMORY:
  1923.      if (this->memory != NULL)
  1924.         farmemfree(this->memory);
  1925.      this->memory = NULL;
  1926.      break;
  1927.       } ;
  1928.  
  1929.    /* allocate space and store the rect */
  1930.  
  1931.    if ( PalTable__MemoryAlloc(this, (long)width*depth) )
  1932.       {
  1933.       char far  *ptr = this->memory;
  1934.       char far  *bufptr = buff; /* MSC needs this indirection to get it right */
  1935.  
  1936.       Cursor_Hide();
  1937.       for (yoff=0; yoff<depth; yoff++)
  1938.      {
  1939.      getrow(this->x, this->y+yoff, width, buff);
  1940.      hline (this->x, this->y+yoff, width, bg_color);
  1941.      movedata(FP_SEG(bufptr), FP_OFF(bufptr), FP_SEG(ptr), FP_OFF(ptr), width);
  1942.      ptr = (char far *)normalize(ptr+width);
  1943.      }
  1944.       Cursor_Show();
  1945.       }
  1946.  
  1947.    else /* to disk */
  1948.       {
  1949.       this->stored_at = DISK;
  1950.  
  1951.       if ( this->file == NULL )
  1952.      {
  1953.      this->file = fopen(FILENAME, "w+b");
  1954.      if (this->file == NULL)
  1955.         {
  1956.         this->stored_at = NOWHERE;
  1957.         buzzer(3);
  1958.         return ;
  1959.         }
  1960.      }
  1961.  
  1962.       rewind(this->file);
  1963.       Cursor_Hide();
  1964.       for (yoff=0; yoff<depth; yoff++)
  1965.      {
  1966.      getrow(this->x, this->y+yoff, width, buff);
  1967.      hline (this->x, this->y+yoff, width, bg_color);
  1968.      if ( fwrite(buff, width, 1, this->file) != 1 )
  1969.         {
  1970.         buzzer(3);
  1971.         break;
  1972.         }
  1973.      }
  1974.       Cursor_Show();
  1975.       }
  1976.  
  1977.    }
  1978.  
  1979.  
  1980. static void PalTable__RestoreRect(PalTable *this)
  1981.    {
  1982.    char buff[MAX_WIDTH];
  1983.    int  width = PalTable_PALX + this->csize*16 + 1 + 1,
  1984.         depth = PalTable_PALY + this->csize*16 + 1 + 1;
  1985.    int  yoff;
  1986.  
  1987.    if (this->hidden)
  1988.       return;
  1989.  
  1990.    switch ( this->stored_at )
  1991.       {
  1992.       case DISK:
  1993.      rewind(this->file);
  1994.      Cursor_Hide();
  1995.      for (yoff=0; yoff<depth; yoff++)
  1996.         {
  1997.         if ( fread(buff, width, 1, this->file) != 1 )
  1998.            {
  1999.            buzzer(3);
  2000.            break;
  2001.            }
  2002.         putrow(this->x, this->y+yoff, width, buff);
  2003.         }
  2004.      Cursor_Show();
  2005.      break;
  2006.  
  2007.       case MEMORY:
  2008.      {
  2009.      char far  *ptr = this->memory;
  2010.      char far  *bufptr = buff; /* MSC needs this indirection to get it right */
  2011.  
  2012.      Cursor_Hide();
  2013.      for (yoff=0; yoff<depth; yoff++)
  2014.         {
  2015.         movedata(FP_SEG(ptr), FP_OFF(ptr), FP_SEG(bufptr), FP_OFF(bufptr), width);
  2016.         putrow(this->x, this->y+yoff, width, buff);
  2017.         ptr = (char far *)normalize(ptr+width);
  2018.         }
  2019.      Cursor_Show();
  2020.      break;
  2021.      }
  2022.  
  2023.       case NOWHERE:
  2024.      break;
  2025.       } /* switch */
  2026.    }
  2027.  
  2028.  
  2029. static void PalTable__SetPos(PalTable *this, int x, int y)
  2030.    {
  2031.    int width = PalTable_PALX + this->csize*16 + 1 + 1;
  2032.  
  2033.    this->x = x;
  2034.    this->y = y;
  2035.  
  2036.    RGBEditor_SetPos(this->rgb[0], x+2, y+2);
  2037.    RGBEditor_SetPos(this->rgb[1], x+width-2-RGBEditor_WIDTH, y+2);
  2038.    }
  2039.  
  2040.  
  2041. static void PalTable__SetCSize(PalTable *this, int csize)
  2042.    {
  2043.    this->csize = csize;
  2044.    PalTable__SetPos(this, this->x, this->y);
  2045.    }
  2046.  
  2047.  
  2048. static int PalTable__GetCursorColor(PalTable *this)
  2049.    {
  2050.    int x     = Cursor_GetX(),
  2051.        y     = Cursor_GetY(),
  2052.        size;
  2053.    int color = getcolor(x, y);
  2054.  
  2055.    if ( is_reserved(color) )
  2056.       {
  2057.       if ( is_in_box(x, y, this->x, this->y, 1+(this->csize*16)+1+1, 2+RGBEditor_DEPTH+2+(this->csize*16)+1+1) )
  2058.      {  /* is the cursor over the editor? */
  2059.      x -= this->x + PalTable_PALX;
  2060.      y -= this->y + PalTable_PALY;
  2061.      size = this->csize;
  2062.  
  2063.      if (x < 0 || y < 0 || x > size*16 || y > size*16)
  2064.         return (-1);
  2065.  
  2066.      if ( x == size*16 )
  2067.         --x;
  2068.      if ( y == size*16 )
  2069.         --y;
  2070.  
  2071.      return ( (y/size)*16 + x/size );
  2072.      }
  2073.       else
  2074.      return (color);
  2075.       }
  2076.  
  2077.    return (color);
  2078.    }
  2079.  
  2080.  
  2081.  
  2082. #define CURS_INC 1
  2083.  
  2084. static void PalTable__DoCurs(PalTable *this, int key)
  2085.    {
  2086.    BOOLEAN done  = FALSE;
  2087.    BOOLEAN first = TRUE;
  2088.    int       xoff  = 0,
  2089.        yoff  = 0;
  2090.  
  2091.    while ( !done )
  2092.       {
  2093.       switch(key)
  2094.      {
  2095.      case RIGHT_ARROW_2:     xoff += CURS_INC*4;   break;
  2096.      case RIGHT_ARROW:     xoff += CURS_INC;     break;
  2097.      case LEFT_ARROW_2:     xoff -= CURS_INC*4;   break;
  2098.      case LEFT_ARROW:     xoff -= CURS_INC;     break;
  2099.      case DOWN_ARROW_2:     yoff += CURS_INC*4;   break;
  2100.      case DOWN_ARROW:     yoff += CURS_INC;     break;
  2101.      case UP_ARROW_2:     yoff -= CURS_INC*4;   break;
  2102.      case UP_ARROW:      yoff -= CURS_INC;     break;
  2103.  
  2104.      default:
  2105.         done = TRUE;
  2106.      }
  2107.  
  2108.       if (!done)
  2109.      {
  2110.      if (!first)
  2111.         getakey();         /* delete key from buffer */
  2112.      else
  2113.         first = FALSE;
  2114.      key = keypressed();   /* peek at the next one... */
  2115.      }
  2116.       }
  2117.  
  2118.    Cursor_Move(xoff, yoff);
  2119.  
  2120.    if (this->auto_select)
  2121.       PalTable__SetCurr(this, this->active, PalTable__GetCursorColor(this));
  2122.    }
  2123.  
  2124.  
  2125. #ifdef __TURBOC__
  2126. #   pragma argsused
  2127. #endif
  2128.  
  2129. static void PalTable__change(RGBEditor *rgb, VOIDPTR info)
  2130.    {
  2131.    PalTable *this = (PalTable *)info;
  2132.    this->pal[this->curr[this->active]] = RGBEditor_GetRGB(rgb);
  2133.  
  2134.    if (this->curr[0] == this->curr[1])
  2135.       {
  2136.       int      other = this->active==0 ? 1 : 0;
  2137.       PALENTRY color;
  2138.  
  2139.       color = RGBEditor_GetRGB(this->rgb[this->active]);
  2140.       RGBEditor_SetRGB(this->rgb[other], this->curr[other], &color);
  2141.  
  2142.       Cursor_Hide();
  2143.       RGBEditor_Update(this->rgb[other]);
  2144.       Cursor_Show();
  2145.       }
  2146.  
  2147.    }
  2148.  
  2149.  
  2150. static void PalTable__UpdateDAC(PalTable *this)
  2151.    {
  2152.    if ( this->exclude )
  2153.       {
  2154.       memset(dacbox, 0, 256*3);
  2155.       if (this->exclude == 1)
  2156.      {
  2157.      int a = this->curr[this->active];
  2158.      memmove(dacbox[a], &this->pal[a], 3);
  2159.      }
  2160.       else
  2161.      {
  2162.      int a = this->curr[0],
  2163.          b = this->curr[1];
  2164.  
  2165.      if (a>b)
  2166.         {
  2167.         int t=a;
  2168.         a=b;
  2169.         b=t;
  2170.         }
  2171.  
  2172.      memmove(dacbox[a], &this->pal[a], 3*(1+(b-a)));
  2173.      }
  2174.       }
  2175.    else
  2176.       memmove(dacbox[0], this->pal, 3*colors);
  2177.  
  2178.    if ( !this->hidden )
  2179.       {
  2180.       if (inverse)
  2181.      {
  2182.      memset(dacbox[fg_color], 0, 3);     /* dacbox[fg] = (0,0,0) */
  2183.      memset(dacbox[bg_color], 48, 3);     /* dacbox[bg] = (48,48,48) */
  2184.      }
  2185.       else
  2186.      {
  2187.      memset(dacbox[bg_color], 0, 3);     /* dacbox[bg] = (0,0,0) */
  2188.      memset(dacbox[fg_color], 48, 3);     /* dacbox[fg] = (48,48,48) */
  2189.      }
  2190.       }
  2191.  
  2192.    spindac(0,1);
  2193.    }
  2194.  
  2195.  
  2196. static void PalTable__Rotate(PalTable *this, int dir)
  2197.    {
  2198.    PALENTRY hold;
  2199.    int        size;
  2200.  
  2201.    size  = 1 + (rotate_hi-rotate_lo);
  2202.  
  2203.    if (dir == 1)
  2204.       {
  2205.       memmove(&hold, &this->pal[rotate_hi],  3);
  2206.       memmove(&this->pal[rotate_lo+1], &this->pal[rotate_lo], 3*(size-1));
  2207.       memmove(&this->pal[rotate_lo], &hold, 3);
  2208.       }
  2209.    else
  2210.       {
  2211.       memmove(&hold, &this->pal[rotate_lo], 3);
  2212.       memmove(&this->pal[rotate_lo], &this->pal[rotate_lo+1], 3*(size-1));
  2213.       memmove(&this->pal[rotate_hi], &hold,  3);
  2214.       }
  2215.  
  2216.    Cursor_Hide();
  2217.  
  2218.    /* update the DAC.  */
  2219.  
  2220.    PalTable__UpdateDAC(this);
  2221.  
  2222.    /* update the editors. */
  2223.  
  2224.    RGBEditor_SetRGB(this->rgb[0], this->curr[0], &(this->pal[this->curr[0]]));
  2225.    RGBEditor_SetRGB(this->rgb[1], this->curr[1], &(this->pal[this->curr[1]]));
  2226.    RGBEditor_Update(this->rgb[0]);
  2227.    RGBEditor_Update(this->rgb[1]);
  2228.  
  2229.    Cursor_Show();
  2230.    }
  2231.  
  2232.  
  2233. static void PalTable__other_key(int key, RGBEditor *rgb, VOIDPTR info)
  2234.    {
  2235.    PalTable *this = (PalTable *)info;
  2236.    BOOLEAN   again;
  2237.  
  2238.    do
  2239.       {
  2240.       again = FALSE;
  2241.  
  2242.       switch(key)
  2243.      {
  2244.      case '\\':    /* move/resize */
  2245.         {
  2246.         if (this->hidden)
  2247.            break;         /* cannot move a hidden pal */
  2248.         Cursor_Hide();
  2249.         PalTable__RestoreRect(this);
  2250.         MoveBox_SetPos(this->movebox, this->x, this->y);
  2251.         MoveBox_SetCSize(this->movebox, this->csize);
  2252.         if ( MoveBox_Process(this->movebox) )
  2253.            {
  2254.            if ( MoveBox_ShouldHide(this->movebox) )
  2255.           PalTable_SetHidden(this, TRUE);
  2256.            else if ( MoveBox_Moved(this->movebox) )
  2257.           {
  2258.           PalTable__SetPos(this, MoveBox_X(this->movebox), MoveBox_Y(this->movebox));
  2259.           PalTable__SetCSize(this, MoveBox_CSize(this->movebox));
  2260.           PalTable__SaveRect(this);
  2261.           }
  2262.            }
  2263.         PalTable__Draw(this);
  2264.         Cursor_Show();
  2265.  
  2266.         RGBEditor_SetDone(this->rgb[this->active], TRUE);
  2267.  
  2268.         if (this->auto_select)
  2269.            PalTable__SetCurr(this, this->active, PalTable__GetCursorColor(this));
  2270.         break;
  2271.         }
  2272.  
  2273.      case 'Y':    /* exclude range */
  2274.      case 'y':
  2275.         if ( this->exclude==2 )
  2276.            this->exclude = 0;
  2277.         else
  2278.            this->exclude = 2;
  2279.         PalTable__UpdateDAC(this);
  2280.         break;
  2281.  
  2282.      case 'X':
  2283.      case 'x':     /* exclude current entry */
  2284.         if ( this->exclude==1 )
  2285.            this->exclude = 0;
  2286.         else
  2287.            this->exclude = 1;
  2288.         PalTable__UpdateDAC(this);
  2289.         break;
  2290.  
  2291.      case RIGHT_ARROW:
  2292.      case LEFT_ARROW:
  2293.      case UP_ARROW:
  2294.      case DOWN_ARROW:
  2295.      case RIGHT_ARROW_2:
  2296.      case LEFT_ARROW_2:
  2297.      case UP_ARROW_2:
  2298.      case DOWN_ARROW_2:
  2299.         PalTable__DoCurs(this, key);
  2300.         break;
  2301.  
  2302.      case ESC:
  2303.         this->done = TRUE;
  2304.         RGBEditor_SetDone(rgb, TRUE);
  2305.         break;
  2306.  
  2307.      case ' ':     /* select the other palette register */
  2308.         this->active = (this->active==0) ? 1 : 0;
  2309.         if (this->auto_select)
  2310.            PalTable__SetCurr(this, this->active, PalTable__GetCursorColor(this));
  2311.          else
  2312.            PalTable__SetCurr(this, -1, 0);
  2313.  
  2314.         if (this->exclude)
  2315.            PalTable__UpdateDAC(this);
  2316.  
  2317.         RGBEditor_SetDone(rgb, TRUE);
  2318.         break;
  2319.  
  2320.      case ENTER:    /* set register to color under cursor.  useful when not */
  2321.      case ENTER_2:  /* in auto_select mode */
  2322.         PalTable__SetCurr(this, this->active, PalTable__GetCursorColor(this));
  2323.  
  2324.         if (this->exclude)
  2325.            PalTable__UpdateDAC(this);
  2326.  
  2327.         RGBEditor_SetDone(rgb, TRUE);
  2328.         break;
  2329.  
  2330.      case 'D':    /* copy (Duplicate?) color in inactive to color in active */
  2331.      case 'd':
  2332.         {
  2333.         int   a = this->active,
  2334.              b = (a==0) ? 1 : 0;
  2335.         PALENTRY t;
  2336.  
  2337.         t = RGBEditor_GetRGB(this->rgb[b]);
  2338.         Cursor_Hide();
  2339.  
  2340.         RGBEditor_SetRGB(this->rgb[a], this->curr[a], &t);
  2341.         RGBEditor_Update(this->rgb[a]);
  2342.         PalTable__change(this->rgb[a], this);
  2343.         this->pal[this->curr[a]] = t;
  2344.         PalTable__UpdateDAC(this);
  2345.  
  2346.         Cursor_Show();
  2347.         break;
  2348.         }
  2349.  
  2350.      case '=':    /* create a shade range between the two entries */
  2351.         {
  2352.         int a = this->curr[0],
  2353.             b = this->curr[1];
  2354.  
  2355.         if (a > b)
  2356.            {
  2357.            int t = a;
  2358.            a = b;
  2359.            b = t;
  2360.            }
  2361.  
  2362.         if (a != b)
  2363.            {
  2364.            mkpalrange(&this->pal[a], &this->pal[b], &this->pal[a], b-a, 1);
  2365.            PalTable__UpdateDAC(this);
  2366.            }
  2367.  
  2368.         break;
  2369.         }
  2370.  
  2371.      case '!':    /* swap r<->g */
  2372.         {
  2373.         int a = this->curr[0],
  2374.         b = this->curr[1];
  2375.  
  2376.         if (a > b)
  2377.            {
  2378.            int t = a;
  2379.            a = b;
  2380.            b = t;
  2381.            }
  2382.  
  2383.         if (a != b)
  2384.            {
  2385.            rotcolrg(&this->pal[a], b-a);
  2386.            PalTable__UpdateDAC(this);
  2387.            }
  2388.  
  2389.         break;
  2390.         }
  2391.  
  2392.      case '@':    /* swap g<->b */
  2393.         {
  2394.         int a = this->curr[0],
  2395.         b = this->curr[1];
  2396.  
  2397.         if (a > b)
  2398.            {
  2399.            int t = a;
  2400.            a = b;
  2401.            b = t;
  2402.            }
  2403.  
  2404.         if (a != b)
  2405.            {
  2406.            rotcolgb(&this->pal[a], b-a);
  2407.            PalTable__UpdateDAC(this);
  2408.            }
  2409.  
  2410.         break;
  2411.         }
  2412.  
  2413.      case '#':    /* swap r<->b */
  2414.         {
  2415.         int a = this->curr[0],
  2416.         b = this->curr[1];
  2417.  
  2418.         if (a > b)
  2419.            {
  2420.            int t = a;
  2421.            a = b;
  2422.            b = t;
  2423.            }
  2424.  
  2425.         if (a != b)
  2426.            {
  2427.            rotcolbr(&this->pal[a], b-a);
  2428.            PalTable__UpdateDAC(this);
  2429.            }
  2430.  
  2431.         break;
  2432.         }
  2433.  
  2434.  
  2435.      case 'T':
  2436.      case 't':   /* s(T)ripe mode */
  2437.         {
  2438.         int key;
  2439.  
  2440.         Cursor_Hide();
  2441.         key = getakeynohelp();
  2442.         Cursor_Show();
  2443.  
  2444.         if (key >= '1' && key <= '9')
  2445.            {
  2446.            int a = this->curr[0],
  2447.            b = this->curr[1];
  2448.  
  2449.            if (a > b)
  2450.           {
  2451.           int t = a;
  2452.           a = b;
  2453.           b = t;
  2454.           }
  2455.  
  2456.            if (a != b)
  2457.           {
  2458.           mkpalrange(&this->pal[a], &this->pal[b], &this->pal[a], b-a, key-'0');
  2459.           PalTable__UpdateDAC(this);
  2460.           }
  2461.            }
  2462.  
  2463.         break;
  2464.         }
  2465.  
  2466.      case 'M':   /* set gamma */
  2467.      case 'm':
  2468.          {
  2469.          int i;
  2470.          char buf[20];
  2471.          sprintf(buf,"%.3f",1./gamma_val);
  2472.          stackscreen();
  2473.          i = field_prompt(0,"Enter gamma value",NULL,buf,20,NULL);
  2474.          unstackscreen();
  2475.          if (i != -1) {
  2476.              sscanf(buf,"%f",&gamma_val);
  2477.              if (gamma_val==0) {
  2478.              gamma_val = 0.0000000001;
  2479.              }
  2480.              gamma_val = 1./gamma_val;
  2481.          }
  2482.          }
  2483.          break;
  2484.      case 'A':   /* toggle auto-select mode */
  2485.      case 'a':
  2486.         this->auto_select = (this->auto_select) ? FALSE : TRUE;
  2487.         if (this->auto_select)
  2488.            {
  2489.            PalTable__SetCurr(this, this->active, PalTable__GetCursorColor(this));
  2490.            if (this->exclude)
  2491.           PalTable__UpdateDAC(this);
  2492.            }
  2493.         break;
  2494.  
  2495.      case 'H':
  2496.      case 'h': /* toggle hide/display of palette editor */
  2497.         Cursor_Hide();
  2498.         PalTable_Hide(this, rgb, (BOOLEAN)((this->hidden) ? FALSE : TRUE));
  2499.         Cursor_Show();
  2500.         break;
  2501.  
  2502.      case '.':   /* rotate once */
  2503.      case ',':
  2504.         {
  2505.             int dir = (key=='.') ? 1 : -1;
  2506.  
  2507.         PalTable__Rotate(this, dir);
  2508.         break;
  2509.         }
  2510.  
  2511.      case '>':   /* continuous rotation (until a key is pressed) */
  2512.      case '<':
  2513.         {
  2514.             int dir = (key=='>') ? 1 : -1;
  2515.         long tick;
  2516.  
  2517.         Cursor_Hide();
  2518.  
  2519.         if ( !this->hidden )
  2520.            {
  2521.            RGBEditor_BlankSampleBox(this->rgb[0]);
  2522.            RGBEditor_BlankSampleBox(this->rgb[1]);
  2523.            RGBEditor_SetHidden(this->rgb[0], TRUE);
  2524.            RGBEditor_SetHidden(this->rgb[1], TRUE);
  2525.            }
  2526.  
  2527.         while ( !keypressed() )
  2528.            {
  2529.            tick = readticker();
  2530.            PalTable__Rotate(this, dir);
  2531.            while (readticker() == tick) ;   /* wait until a tick passes */
  2532.            }
  2533.  
  2534.         key = getakey();
  2535.         again = (key=='<' || key=='>') ? TRUE : FALSE;
  2536.  
  2537.         if ( !this->hidden )
  2538.            {
  2539.            RGBEditor_SetHidden(this->rgb[0], FALSE);
  2540.            RGBEditor_SetHidden(this->rgb[1], FALSE);
  2541.            RGBEditor_Update(this->rgb[0]);
  2542.            RGBEditor_Update(this->rgb[1]);
  2543.            }
  2544.  
  2545.         Cursor_Show();
  2546.         break;
  2547.         }
  2548.  
  2549.      case 'I':     /* invert the fg & bg colors */
  2550.      case 'i':
  2551.        inverse = !inverse;
  2552.        PalTable__UpdateDAC(this);
  2553.        break;
  2554.  
  2555.      case 'V':
  2556.      case 'v':     /* set the reserved colors to the editor colors */
  2557.         if ( this->curr[0] >= colors || this->curr[1] >= colors ||
  2558.          this->curr[0] == this->curr[1] )
  2559.            {
  2560.            buzzer(2);
  2561.            break;
  2562.            }
  2563.  
  2564.         fg_color = this->curr[0];
  2565.         bg_color = this->curr[1];
  2566.  
  2567.         if ( !this->hidden )
  2568.            {
  2569.            Cursor_Hide();
  2570.            PalTable__UpdateDAC(this);
  2571.            PalTable__Draw(this);
  2572.            Cursor_Show();
  2573.            }
  2574.  
  2575.         RGBEditor_SetDone(this->rgb[this->active], TRUE);
  2576.         break;
  2577.  
  2578.      case 'O':    /* set rotate_lo and rotate_hi to editors */
  2579.      case 'o':
  2580.         if (this->curr[0] > this->curr[1])
  2581.            {
  2582.            rotate_lo = this->curr[1];
  2583.            rotate_hi = this->curr[0];
  2584.            }
  2585.         else
  2586.            {
  2587.            rotate_lo = this->curr[0];
  2588.            rotate_hi = this->curr[1];
  2589.            }
  2590.         break;
  2591.  
  2592.      case F2:      /* restore a palette */
  2593.      case F3:
  2594.      case F4:
  2595.      case F5:
  2596.      case F6:
  2597.      case F7:
  2598.      case F8:
  2599.      case F9:
  2600.         {
  2601.         int which = key - F2;
  2602.  
  2603.         if ( this->save_pal[which] != NULL )
  2604.            {
  2605.            struct SREGS seg;
  2606.  
  2607.            Cursor_Hide();
  2608.  
  2609.            segread(&seg);
  2610.            movedata(FP_SEG(this->save_pal[which]), FP_OFF(this->save_pal[which]),
  2611.                 seg.ds, (unsigned)(this->pal), 256*3);
  2612.  
  2613.            PalTable__UpdateDAC(this);
  2614.  
  2615.            PalTable__SetCurr(this, -1, 0);
  2616.            Cursor_Show();
  2617.            RGBEditor_SetDone(this->rgb[this->active], TRUE);
  2618.            }
  2619.         else
  2620.            buzzer(3);     /* error buzz */
  2621.         break;
  2622.         }
  2623.  
  2624.      case SF2:   /* save a palette */
  2625.      case SF3:
  2626.      case SF4:
  2627.      case SF5:
  2628.      case SF6:
  2629.      case SF7:
  2630.      case SF8:
  2631.      case SF9:
  2632.         {
  2633.         int which = key - SF2;
  2634.  
  2635.         if ( this->save_pal[which] != NULL )
  2636.            {
  2637.            struct SREGS seg;
  2638.  
  2639.            segread(&seg);
  2640.            movedata(seg.ds, (unsigned)(this->pal), FP_SEG(this->save_pal[which]),
  2641.                FP_OFF(this->save_pal[which]), 256*3);
  2642.            }
  2643.         else
  2644.            buzzer(3); /* oops! short on memory! */
  2645.         break;
  2646.         }
  2647.  
  2648.      case 'L':     /* load a .map palette */
  2649.      case 'l':
  2650.         {
  2651.         load_palette();
  2652. #ifndef XFRACT
  2653.         getpalrange(0, colors, this->pal);
  2654. #else
  2655.         getpalrange(0, 256, this->pal);
  2656. #endif
  2657.         PalTable__UpdateDAC(this);
  2658.         RGBEditor_SetRGB(this->rgb[0], this->curr[0], &(this->pal[this->curr[0]]));
  2659.         RGBEditor_Update(this->rgb[0]);
  2660.         RGBEditor_SetRGB(this->rgb[1], this->curr[1], &(this->pal[this->curr[1]]));
  2661.         RGBEditor_Update(this->rgb[1]);
  2662.         break;
  2663.         }
  2664.  
  2665.      case 'S':     /* save a .map palette */
  2666.      case 's':
  2667.         {
  2668. #ifndef XFRACT
  2669.         setpalrange(0, colors, this->pal);
  2670. #else
  2671.         setpalrange(0, 256, this->pal);
  2672. #endif
  2673.         save_palette();
  2674.         PalTable__UpdateDAC(this);
  2675.         break;
  2676.         }
  2677.  
  2678.      case 'C':     /* color cycling sub-mode */
  2679.      case 'c':
  2680.         {
  2681.         BOOLEAN oldhidden = this->hidden;
  2682.  
  2683.         Cursor_Hide();
  2684.         if ( !oldhidden )
  2685.            PalTable_Hide(this, rgb, TRUE);
  2686.         setpalrange(0, colors, this->pal);
  2687.         rotate(0);
  2688.         getpalrange(0, colors, this->pal);
  2689.         PalTable__UpdateDAC(this);
  2690.         if ( !oldhidden )
  2691.            {
  2692.            RGBEditor_SetRGB(this->rgb[0], this->curr[0], &(this->pal[this->curr[0]]));
  2693.            RGBEditor_SetRGB(this->rgb[1], this->curr[1], &(this->pal[this->curr[1]]));
  2694.            PalTable_Hide(this, rgb, FALSE);
  2695.            }
  2696.         Cursor_Show();
  2697.         break;
  2698.         }
  2699.  
  2700.      case 'W':   /* convert to greyscale */
  2701.      case 'w':
  2702.         {
  2703.         switch ( this->exclude )
  2704.            {
  2705.            case 0:   /* normal mode.  convert all colors to grey scale */
  2706.           palrangetogrey(this->pal, 0, 256);
  2707.           break;
  2708.  
  2709.            case 1:   /* 'x' mode. convert current color to grey scale.  */
  2710.           palrangetogrey(this->pal, this->curr[this->active], 1);
  2711.           break;
  2712.  
  2713.            case 2:  /* 'y' mode.  convert range between editors to grey. */
  2714.           {
  2715.           int a = this->curr[0],
  2716.               b = this->curr[1];
  2717.  
  2718.           if (a > b)
  2719.              {
  2720.              int t = a;
  2721.              a = b;
  2722.              b = t;
  2723.              }
  2724.  
  2725.           palrangetogrey(this->pal, a, 1+(b-a));
  2726.           break;
  2727.           }
  2728.            }
  2729.  
  2730.         PalTable__UpdateDAC(this);
  2731.         RGBEditor_SetRGB(this->rgb[0], this->curr[0], &(this->pal[this->curr[0]]));
  2732.         RGBEditor_Update(this->rgb[0]);
  2733.         RGBEditor_SetRGB(this->rgb[1], this->curr[1], &(this->pal[this->curr[1]]));
  2734.         RGBEditor_Update(this->rgb[1]);
  2735.         break;
  2736.         }
  2737.  
  2738.      case 'N':   /* convert to negative color */
  2739.      case 'n':
  2740.         {
  2741.         switch ( this->exclude )
  2742.            {
  2743.            case 0:     /* normal mode.  convert all colors to grey scale */
  2744.           palrangetonegative(this->pal, 0, 256);
  2745.           break;
  2746.  
  2747.            case 1:     /* 'x' mode. convert current color to grey scale.  */
  2748.           palrangetonegative(this->pal, this->curr[this->active], 1);
  2749.           break;
  2750.  
  2751.            case 2:  /* 'y' mode.  convert range between editors to grey. */
  2752.           {
  2753.           int a = this->curr[0],
  2754.               b = this->curr[1];
  2755.  
  2756.           if (a > b)
  2757.              {
  2758.              int t = a;
  2759.              a = b;
  2760.              b = t;
  2761.              }
  2762.  
  2763.           palrangetonegative(this->pal, a, 1+(b-a));
  2764.           break;
  2765.           }
  2766.            }
  2767.  
  2768.         PalTable__UpdateDAC(this);
  2769.         RGBEditor_SetRGB(this->rgb[0], this->curr[0], &(this->pal[this->curr[0]]));
  2770.         RGBEditor_Update(this->rgb[0]);
  2771.         RGBEditor_SetRGB(this->rgb[1], this->curr[1], &(this->pal[this->curr[1]]));
  2772.         RGBEditor_Update(this->rgb[1]);
  2773.         break;
  2774.         }
  2775.  
  2776.      } /* switch */
  2777.       }
  2778.    while (again);
  2779.    }
  2780.  
  2781.  
  2782. static void PalTable__MkDefaultPalettes(PalTable *this)  /* creates default Fkey palettes */
  2783.    {
  2784.    PALENTRY     black,
  2785.             white;
  2786.    PALENTRY     temp[256];
  2787.    int            ctr;
  2788.    struct SREGS seg;
  2789.  
  2790.    black.red = black.green = black.blue = 0;
  2791.    white.red = white.green = white.blue = 63;
  2792.    mkpalrange(&black, &white, temp, 256, 1); /* boring! */
  2793.  
  2794.    segread(&seg);
  2795.  
  2796.    for (ctr=0; ctr<8; ctr++)   /* copy temp into all fkey saves */
  2797.       movedata(seg.ss, (unsigned)(temp), FP_SEG(this->save_pal[ctr]),
  2798.            FP_OFF(this->save_pal[ctr]), 256*3);
  2799.    }
  2800.  
  2801.  
  2802.  
  2803. static PalTable *PalTable_Construct(void)
  2804.    {
  2805.    PalTable     *this = new(PalTable);
  2806.    int         csize;
  2807.    int         ctr;
  2808.    PALENTRY far *mem_block;
  2809.    void far     *temp;
  2810.  
  2811.    temp = farmemalloc(FAR_RESERVE);
  2812.  
  2813.    if ( temp != NULL )
  2814.       {
  2815.       mem_block = (PALENTRY far *)farmemalloc(256L*3 * 8);
  2816.  
  2817.       if ( mem_block == NULL )
  2818.      {
  2819.      for (ctr=0; ctr<8; ctr++)
  2820.         this->save_pal[ctr] = NULL;
  2821.      }
  2822.       else
  2823.      {
  2824.      for (ctr=0; ctr<8; ctr++)
  2825.         this->save_pal[ctr] = mem_block + (256*ctr);
  2826.  
  2827.      PalTable__MkDefaultPalettes(this);
  2828.      }
  2829.       farmemfree(temp);
  2830.       }
  2831.  
  2832.    this->rgb[0] = RGBEditor_Construct(0, 0, PalTable__other_key,
  2833.           PalTable__change, this);
  2834.    this->rgb[1] = RGBEditor_Construct(0, 0, PalTable__other_key,
  2835.           PalTable__change, this);
  2836.  
  2837.    this->movebox = MoveBox_Construct(0,0,0, PalTable_PALX+1, PalTable_PALY+1);
  2838.  
  2839.    this->active      = 0;
  2840.    this->curr[0]     = 1;
  2841.    this->curr[1]     = 1;
  2842.    this->auto_select = TRUE;
  2843.    this->exclude     = FALSE;
  2844.    this->hidden      = FALSE;
  2845.    this->stored_at   = NOWHERE;
  2846.    this->file         = NULL;
  2847.    this->memory      = NULL;
  2848.  
  2849.  
  2850.    RGBEditor_SetRGB(this->rgb[0], this->curr[0], &this->pal[this->curr[0]]);
  2851.    RGBEditor_SetRGB(this->rgb[1], this->curr[1], &this->pal[this->curr[0]]);
  2852.  
  2853.    PalTable__SetPos(this, 0, 0);
  2854.  
  2855.    csize = ( (sydots-(PalTable_PALY+1+1)) / 2 ) / 16;
  2856.    if (csize<CSIZE_MIN)
  2857.       csize = CSIZE_MIN;
  2858.    PalTable__SetCSize(this, csize);
  2859.  
  2860.    return(this);
  2861.    }
  2862.  
  2863.  
  2864. static void PalTable_SetHidden(PalTable *this, BOOLEAN hidden)
  2865.    {
  2866.    this->hidden = hidden;
  2867.    RGBEditor_SetHidden(this->rgb[0], hidden);
  2868.    RGBEditor_SetHidden(this->rgb[1], hidden);
  2869.    PalTable__UpdateDAC(this);
  2870.    }
  2871.  
  2872.  
  2873. static void PalTable_Hide(PalTable *this, RGBEditor *rgb, BOOLEAN hidden)
  2874.    {
  2875.    if (hidden)
  2876.       {
  2877.       PalTable__RestoreRect(this);
  2878.       PalTable_SetHidden(this, TRUE);
  2879.       reserve_colors = FALSE;
  2880.       if (this->auto_select)
  2881.      PalTable__SetCurr(this, this->active, PalTable__GetCursorColor(this));
  2882.       }
  2883.    else
  2884.       {
  2885.       PalTable_SetHidden(this, FALSE);
  2886.       reserve_colors = TRUE;
  2887.       if (this->stored_at == NOWHERE)  /* do we need to save screen? */
  2888.      PalTable__SaveRect(this);
  2889.       PalTable__Draw(this);
  2890.       if (this->auto_select)
  2891.      PalTable__SetCurr(this, this->active, PalTable__GetCursorColor(this));
  2892.       RGBEditor_SetDone(rgb, TRUE);
  2893.       }
  2894.    }
  2895.  
  2896.  
  2897. static void PalTable_Destroy(PalTable *this)
  2898.    {
  2899.  
  2900.    if (this->file != NULL)
  2901.       {
  2902.       fclose(this->file);
  2903.       remove(FILENAME);
  2904.       }
  2905.  
  2906.    if (this->memory != NULL)
  2907.       farmemfree(this->memory);
  2908.  
  2909.    if (this->save_pal[0] != NULL)
  2910.       farmemfree((BYTE far *)this->save_pal[0]);
  2911.  
  2912.    RGBEditor_Destroy(this->rgb[0]);
  2913.    RGBEditor_Destroy(this->rgb[1]);
  2914.    MoveBox_Destroy(this->movebox);
  2915.    delete(this);
  2916.    }
  2917.  
  2918.  
  2919. static void PalTable_Process(PalTable *this)
  2920.    {
  2921.    getpalrange(0, colors, this->pal);
  2922.    PalTable__UpdateDAC(this);
  2923.  
  2924.    RGBEditor_SetRGB(this->rgb[0], this->curr[0], &this->pal[this->curr[0]]);
  2925.    RGBEditor_SetRGB(this->rgb[1], this->curr[1], &this->pal[this->curr[0]]);
  2926.  
  2927.    if (!this->hidden)
  2928.       {
  2929.       MoveBox_SetPos(this->movebox, this->x, this->y);
  2930.       MoveBox_SetCSize(this->movebox, this->csize);
  2931.       if ( !MoveBox_Process(this->movebox) )
  2932.      {
  2933.      setpalrange(0, colors, this->pal);
  2934.      return ;
  2935.      }
  2936.  
  2937.       PalTable__SetPos(this, MoveBox_X(this->movebox), MoveBox_Y(this->movebox));
  2938.       PalTable__SetCSize(this, MoveBox_CSize(this->movebox));
  2939.  
  2940.       if ( MoveBox_ShouldHide(this->movebox) )
  2941.      {
  2942.      PalTable_SetHidden(this, TRUE);
  2943.      reserve_colors = FALSE;   /* <EAN> */
  2944.      }
  2945.       else
  2946.      {
  2947.      reserve_colors = TRUE;    /* <EAN> */
  2948.      PalTable__SaveRect(this);
  2949.      PalTable__Draw(this);
  2950.      }
  2951.       }
  2952.  
  2953.    PalTable__SetCurr(this, this->active,      PalTable__GetCursorColor(this));
  2954.    PalTable__SetCurr(this, (this->active==1)?0:1, PalTable__GetCursorColor(this));
  2955.    Cursor_Show();
  2956.  
  2957.    this->done = FALSE;
  2958.  
  2959.    while ( !this->done )
  2960.       RGBEditor_Edit(this->rgb[this->active]);
  2961.  
  2962.    Cursor_Hide();
  2963.    PalTable__RestoreRect(this);
  2964.    setpalrange(0, colors, this->pal);
  2965.    }
  2966.  
  2967.  
  2968. /*
  2969.  * interface to FRACTINT
  2970.  */
  2971.  
  2972.  
  2973.  
  2974. void EditPalette(void)         /* called by fractint */
  2975.    {
  2976.    int         oldlookatmouse = lookatmouse;
  2977.    int         oldsxoffs        = sxoffs;
  2978.    int         oldsyoffs        = syoffs;
  2979.    PalTable *pt;
  2980.  
  2981.    ENTER_OVLY(OVLY_ROTATE);
  2982.  
  2983.    mem_init(strlocn, 10*1024);
  2984.  
  2985.    if ( (font8x8 = findfont(0)) == NULL )
  2986.       return ;
  2987.  
  2988.    plot = putcolor;
  2989.  
  2990.    line_buff = newx(max(sxdots,sydots));
  2991.  
  2992.    lookatmouse = 3;
  2993.    sxoffs = syoffs = 0;
  2994.  
  2995.    reserve_colors = TRUE;
  2996.    inverse = FALSE;
  2997.    fg_color = 255%colors;
  2998.    bg_color = fg_color-1;
  2999.  
  3000.    Cursor_Construct();
  3001.    pt = PalTable_Construct();
  3002.    PalTable_Process(pt);
  3003.    PalTable_Destroy(pt);
  3004.    Cursor_Destroy();
  3005.  
  3006.    lookatmouse = oldlookatmouse;
  3007.    sxoffs = oldsxoffs;
  3008.    syoffs = oldsyoffs;
  3009.    delete(line_buff);
  3010.    EXIT_OVLY;
  3011.    }
  3012.